Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline Execution #8148

Merged
merged 24 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ class ExecuteExpressionHandler(
) =>
contextRegistry ! ContextRegistryProtocol.ExecuteExpression(
clientId,
params.executionContextId,
params.visualizationId,
params.expressionId,
params.visualizationConfig
params.expression
)
val cancellable =
context.system.scheduler.scheduleOnce(timeout, self, RequestTimeout)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,13 @@ final class ContextRegistry(
sender() ! AccessDenied
}

case ExecuteExpression(clientId, visualizationId, expressionId, cfg) =>
val contextId = cfg.executionContextId
case ExecuteExpression(
clientId,
contextId,
visualizationId,
expressionId,
expression
) =>
if (store.hasContext(clientId, contextId)) {
store.getListener(contextId).foreach { listener =>
listener ! RegisterOneshotVisualization(
Expand All @@ -272,17 +277,18 @@ final class ContextRegistry(
)
}
val handler = context.actorOf(
AttachVisualizationHandler.props(
ExecuteExpressionHandler.props(
runtimeFailureMapper,
timeout,
runtime
)
)
handler.forward(
Api.AttachVisualization(
Api.ExecuteExpression(
contextId,
visualizationId,
expressionId,
cfg.toApi
expression
)
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.enso.languageserver.filemanager.{FileSystemFailure, Path}
import org.enso.languageserver.libraries.LibraryComponentGroup
import org.enso.languageserver.runtime.ExecutionApi.ContextId
import org.enso.languageserver.session.JsonSession
import org.enso.logger.masking.ToLogString
import org.enso.logger.masking.{MaskedString, ToLogString}
import org.enso.text.editing.model

import java.util.UUID
Expand Down Expand Up @@ -422,23 +422,23 @@ object ContextRegistryProtocol {
* @param clientId the requester id
* @param visualizationId an identifier of a visualization
* @param expressionId an identifier of an expression which is visualised
* @param visualizationConfig a configuration object for properties of the
* visualization
* @param expression the expression to execute
*/
case class ExecuteExpression(
clientId: ClientId,
executionContextId: UUID,
visualizationId: UUID,
expressionId: UUID,
visualizationConfig: VisualizationConfiguration
expression: String
) extends ToLogString {

/** @inheritdoc */
override def toLogString(shouldMask: Boolean): String =
"ExecuteExpression(" +
s"clientId=$clientId," +
s"visualizationId=$visualizationId," +
s"expressionId=$expressionId,visualizationConfig=" +
visualizationConfig.toLogString(shouldMask) +
s"expressionId=$expressionId,expression=" +
MaskedString(expression).toLogString(shouldMask) +
")"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ object VisualizationApi {
extends Method("executionContext/executeExpression") {

case class Params(
executionContextId: UUID,
visualizationId: UUID,
expressionId: UUID,
visualizationConfig: VisualizationConfiguration
expression: String
)

implicit val hasParams: HasParams.Aux[this.type, ExecuteExpression.Params] =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.enso.languageserver.runtime.handler

import akka.actor.{Actor, ActorRef, Cancellable, Props}
import akka.pattern.pipe
import com.typesafe.scalalogging.LazyLogging
import org.enso.languageserver.requesthandler.RequestTimeout
import org.enso.languageserver.runtime.{
ContextRegistryProtocol,
RuntimeFailureMapper
}
import org.enso.languageserver.util.UnhandledLogging
import org.enso.polyglot.runtime.Runtime.Api

import java.util.UUID

import scala.concurrent.duration.FiniteDuration

/** A request handler for execute expression commands.
*
* @param runtimeFailureMapper mapper for runtime failures
* @param timeout request timeout
* @param runtime reference to the runtime connector
*/
class ExecuteExpressionHandler(
runtimeFailureMapper: RuntimeFailureMapper,
timeout: FiniteDuration,
runtime: ActorRef
) extends Actor
with LazyLogging
with UnhandledLogging {

import context.dispatcher

override def receive: Receive = requestStage

private def requestStage: Receive = { case msg: Api.ExecuteExpression =>
runtime ! Api.Request(UUID.randomUUID(), msg)
val cancellable =
context.system.scheduler.scheduleOnce(timeout, self, RequestTimeout)
context.become(responseStage(sender(), cancellable))
}

private def responseStage(
replyTo: ActorRef,
cancellable: Cancellable
): Receive = {
case RequestTimeout =>
replyTo ! RequestTimeout
context.stop(self)

case Api.Response(_, Api.VisualizationAttached()) =>
replyTo ! ContextRegistryProtocol.VisualizationAttached
cancellable.cancel()
context.stop(self)

case Api.Response(_, error: Api.Error) =>
runtimeFailureMapper.mapApiError(error).pipeTo(replyTo)
cancellable.cancel()
context.stop(self)
}

}

object ExecuteExpressionHandler {

/** Creates configuration object used to create a [[ExecuteExpressionHandler]].
*
* @param runtimeFailureMapper mapper for runtime failures
* @param timeout request timeout
* @param runtime reference to the runtime connector
*/
def props(
runtimeFailureMapper: RuntimeFailureMapper,
timeout: FiniteDuration,
runtime: ActorRef
): Props =
Props(
new ExecuteExpressionHandler(runtimeFailureMapper, timeout, runtime)
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.enso.polyglot.debugger;

import java.util.UUID;

public final class DefaultExecutionSupport implements IdExecutionService.ExecutionSupport {

private static final DefaultExecutionSupport INSTANCE = new DefaultExecutionSupport();

private DefaultExecutionSupport() {}

public static IdExecutionService.ExecutionSupport getInstance() {
return INSTANCE;
}

@Override
public Object findCachedResult(Object materializedFrame, Object node, UUID nodeId) {
return null;
}

@Override
public void updateCachedResult(UUID nodeId, Object result, boolean isPanic, long nanoElapsedTime) {}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.enso.polyglot.debugger;

import java.util.UUID;

public record ExecutedVisualization(
Object result,
Throwable error,
UUID visualizationId,
UUID expressionId,
Object expressionValue) {}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ public interface IdExecutionService {
String INSTRUMENT_ID = "id-value-extractor";

public interface Callbacks {

void onEnter(UUID nodeId);

void onExpressionReturn(UUID nodeId, Object result, long nanoElapsedTime);

/**
* Notification when a returned value is a function.
*
* @param nodeId identification of the node to be computed
* @param result info about function call
* @return {@code null} should the execution of the node be performed; any other value to skip
* the execution and return the value as a result.
*/
Object onFunctionReturn(UUID nodeId, TruffleObject result);
}

public interface ExecutionSupport {
4e6 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Finds out previously computed result for given id. If a result is returned, then the
* execution of given node is skipped and the value is returned back.
Expand All @@ -18,27 +36,17 @@ public interface Callbacks {
* @return {@code null} should the execution of the node be performed; any other value to skip
* the execution and return the value as a result.
*/
Object findCachedResult(UUID nodeId);
Object findCachedResult(Object materializedFrame, Object node, UUID nodeId);

/**
* Notifies when an execution of a node is over.
*
* @param nodeId identification of the node to be computed
* @param nodeId expression node id that has been computed
* @param result the just computed result
* @param isPanic was the result a panic?
* @param nanoElapsedTime how long it took to compute the result?
*/
void updateCachedResult(UUID nodeId, Object result, boolean isPanic, long nanoElapsedTime);

/**
* Notification when a returned value is a function.
*
* @param nodeId identification of the node to be computed
* @param result info about function call
* @return {@code null} should the execution of the node be performed; any other value to skip
* the execution and return the value as a result.
*/
Object onFunctionReturn(UUID nodeId, TruffleObject result);
}

/**
Expand All @@ -51,5 +59,5 @@ public interface Callbacks {
* @return a reference to the attached event node factory.
*/
EventBinding<ExecutionEventNodeFactory> bind(
TruffleObject module, CallTarget entryCallTarget, Callbacks callbacks, Object timer);
TruffleObject module, CallTarget entryCallTarget, Callbacks callbacks, ExecutionSupport executionSupport, Object timer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ object Runtime {
value = classOf[Api.AttachVisualization],
name = "attachVisualization"
),
new JsonSubTypes.Type(
value = classOf[Api.ExecuteExpression],
name = "executeExpression"
),
new JsonSubTypes.Type(
value = classOf[Api.VisualizationAttached],
name = "visualizationAttached"
Expand Down Expand Up @@ -1553,6 +1557,13 @@ object Runtime {
*/
final case class InitializedNotification() extends ApiResponse

final case class ExecuteExpression(
contextId: ContextId,
visualizationId: VisualizationId,
expressionId: ExpressionId,
expression: String
) extends ApiRequest

/** A request sent from the client to the runtime server, to create a new
* visualization for an expression identified by `expressionId`.
*
Expand Down
Loading
Loading