Skip to content

Commit

Permalink
Send PendingInterrupted on interrupt
Browse files Browse the repository at this point in the history
The information could be used in GUI to indicate pending execution that
will take tad longer.
  • Loading branch information
hubertp committed Dec 19, 2024
1 parent d8736a1 commit e218c94
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 4 deletions.
6 changes: 5 additions & 1 deletion docs/language-server/protocol-language-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ interface ExpressionUpdate {
An information about the computed value.

```typescript
type ExpressionUpdatePayload = Value | DatafalowError | Panic | Pending;
type ExpressionUpdatePayload = Value | DataflowError | Panic | Pending | PendingInterrupted;

/** Indicates that the expression was computed to a value. */
interface Value {
Expand Down Expand Up @@ -426,6 +426,10 @@ interface Pending {
progress?: number;
}

/** Indicates that the computation of the expression has been interrupted
* and will retried */
interface PendingInterrupted { }

/** Information about warnings associated with the value. */
interface Warnings {
/** The number of attached warnings. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ final class ContextEventsListener(
case Api.ExpressionUpdate.Payload.Pending(m, p) =>
ContextRegistryProtocol.ExpressionUpdate.Payload.Pending(m, p)

case Api.ExpressionUpdate.Payload.PendingInterrupted =>
ContextRegistryProtocol.ExpressionUpdate.Payload.PendingInterrupted

case Api.ExpressionUpdate.Payload.DataflowError(trace) =>
ContextRegistryProtocol.ExpressionUpdate.Payload.DataflowError(trace)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,15 @@ object ContextRegistryProtocol {
)
}

/** Indicates that an expression is pending a computation
*/
case class Pending(message: Option[String], progress: Option[Double])
extends Payload

/** Indicates that an expression's computation has been interrupted and shall be retried.
*/
case object PendingInterrupted extends Payload

/** Indicates that the expression was computed to an error.
*
* @param trace the list of expressions leading to the root error.
Expand All @@ -258,6 +264,8 @@ object ContextRegistryProtocol {

val Pending = "Pending"

val PendingInterrupted = "PendingInterrupted"

val DataflowError = "DataflowError"

val Panic = "Panic"
Expand Down Expand Up @@ -291,6 +299,14 @@ object ContextRegistryProtocol {
.deepMerge(
Json.obj(CodecField.Type -> PayloadType.Pending.asJson)
)
case m: Payload.PendingInterrupted.type =>
Encoder[Payload.PendingInterrupted.type]
.apply(m)
.deepMerge(
Json.obj(
CodecField.Type -> PayloadType.PendingInterrupted.asJson
)
)
}

implicit val decoder: Decoder[Payload] =
Expand All @@ -307,6 +323,9 @@ object ContextRegistryProtocol {

case PayloadType.Pending =>
Decoder[Payload.Pending].tryDecode(cursor)

case PayloadType.PendingInterrupted =>
Decoder[Payload.PendingInterrupted.type].tryDecode(cursor)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,16 @@ object Runtime {
)
}

/** TBD
/** Indicates that an expression is pending a computation
*/
@named("expressionUpdatePayloadPending")
case class Pending(message: Option[String], progress: Option[Double])
extends Payload;
extends Payload

/** Indicates that an expression's computation has been interrupted and shall be retried.
*/
@named("expressionUpdatePayloadPendingInterrupted")
case object PendingInterrupted extends Payload

/** Indicates that the expression was computed to an error.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ object ProgramExecutionSupport {
if (VisualizationResult.isInterruptedException(value.getValue)) {
value.getValue match {
case e: AbstractTruffleException =>
// Bail out early. Any references to the value will return `No_Such_Method` exception
sendInterruptedExpressionUpdate(
contextId,
executionFrame.syncState,
value
)
// Bail out early. Any references to this value that do not expect
// Interrupted error will likely return `No_Such_Method` otherwise.
throw new ThreadInterruptedException(e);
case _ =>
}
Expand Down Expand Up @@ -386,6 +392,49 @@ object ProgramExecutionSupport {
Api.ExecutionResult.Failure(ex.getMessage, None)
}

private def sendInterruptedExpressionUpdate(
contextId: ContextId,
syncState: UpdatesSynchronizationState,
value: ExpressionValue
)(implicit ctx: RuntimeContext): Unit = {
val expressionId = value.getExpressionId
val methodCall = toMethodCall(value)
if (
!syncState.isExpressionSync(expressionId) ||
(methodCall.isDefined && !syncState.isMethodPointerSync(
expressionId
))
) {
val payload = Api.ExpressionUpdate.Payload.PendingInterrupted
ctx.endpoint.sendToClient(
Api.Response(
Api.ExpressionUpdates(
contextId,
Set(
Api.ExpressionUpdate(
value.getExpressionId,
Option(value.getTypes).map(_.toVector),
methodCall,
value.getProfilingInfo.map { case e: ExecutionTime =>
Api.ProfilingInfo.ExecutionTime(e.getNanoTimeElapsed)
}.toVector,
value.wasCached(),
value.isTypeChanged || value.isFunctionCallChanged,
payload
)
)
)
)
)

syncState.setExpressionSync(expressionId)
ctx.state.expressionExecutionState.setExpressionExecuted(expressionId)
if (methodCall.isDefined) {
syncState.setMethodPointerSync(expressionId)
}
}
}

private def sendExpressionUpdate(
contextId: ContextId,
syncState: UpdatesSynchronizationState,
Expand Down

0 comments on commit e218c94

Please sign in to comment.