diff --git a/src/GToolkit-GemStone-Lepiter/GtGemStoneSnippetPromise.class.st b/src/GToolkit-GemStone-Lepiter/GtGemStoneSnippetPromise.class.st index d12b4463..d18ca538 100644 --- a/src/GToolkit-GemStone-Lepiter/GtGemStoneSnippetPromise.class.st +++ b/src/GToolkit-GemStone-Lepiter/GtGemStoneSnippetPromise.class.st @@ -28,6 +28,14 @@ GtGemStoneSnippetPromise >> coderEvaluationContext: anObject [ coderEvaluationContext := anObject ] +{ #category : #utils } +GtGemStoneSnippetPromise >> createEvaluationResultFromData: aDictionaryOrObject [ + "Instantiate an evaluation result object from the given object." + + ^ GtGemstoneEvaluationResult + createEvaluationResultFromData: aDictionaryOrObject +] + { #category : #accessing } GtGemStoneSnippetPromise >> gemStoneSession [ ^ gtRsrEvaluatorPromise gtSession @@ -50,8 +58,8 @@ GtGemStoneSnippetPromise >> hasResult [ { #category : #initialization } GtGemStoneSnippetPromise >> initialize [ - super initialize. + value := self. mutex := Mutex new. ] @@ -69,6 +77,22 @@ GtGemStoneSnippetPromise >> isResolved [ value ~~ self ] ] +{ #category : #private } +GtGemStoneSnippetPromise >> resolveWithComputedResult: computedResult [ + computedResult associationsDo: [ :binding | + (snippetCoderModel pharoBindings bindingOf: binding key asSymbol) + value: (binding value asGtBareProxyObject) ]. + + value := (computedResult + at: 'snippetResult' + ifPresent: [ :obj | + coderEvaluationContext serializationStrategy + ifNil: [ obj ] + ifNotNil: [ :strategy | obj + proxyPerform: #yourself serializationStrategy: strategy ] ] + ifAbsent: [ self error: 'no result' ]) asGtBareProxyObject. +] + { #category : #accessing } GtGemStoneSnippetPromise >> resolvedValue [ self assert: [ value ~~ self ]. @@ -108,26 +132,23 @@ GtGemStoneSnippetPromise >> value [ { #category : #private } GtGemStoneSnippetPromise >> wait [ - | result | + | rawEvaluationResultData evaluationResult computedResult | executionContext := gtRsrEvaluatorPromise value. - result := executionContext wait. - - "We get here in case we terminate the remote process running the async computation and signal the semaphore on which the computation runs. A different way to implement this would be to do a low-level call and get back a result object indicating that the process was terminated. It also works here to check against nil, as we expect to get back a dictionary. If the computation could return nil, this would not work." - result ifNil: [ - value := nil. - ^ self ]. + rawEvaluationResultData := executionContext wait. - result associationsDo: [ :binding | - (snippetCoderModel pharoBindings bindingOf: binding key asSymbol) - value: (binding value asGtBareProxyObject) ]. - - value := (result - at: 'snippetResult' - ifPresent: [ :obj | - coderEvaluationContext serializationStrategy - ifNil: [ obj ] - ifNotNil: [ :strategy | obj - proxyPerform: #yourself serializationStrategy: strategy ] ] - ifAbsent: [ self error: 'no result' ]) asGtBareProxyObject. + evaluationResult := self createEvaluationResultFromData: rawEvaluationResultData. + self gemStoneSession ifNotNil: [ :aGemStoneSession | + evaluationResult gtPharoProxyInitializeWithSession: aGemStoneSession ]. + + evaluationResult hasEvaluationException ifTrue: [ + evaluationResult := evaluationResult signalGemStoneDebugger. + self gemStoneSession ifNotNil: [ :aGemStoneSession | + evaluationResult gtPharoProxyInitializeWithSession: aGemStoneSession ]. ]. + + computedResult := evaluationResult computedResult. + computedResult := gtRsrEvaluatorPromise + basicDeserializeResult: evaluationResult computedResult. + + self resolveWithComputedResult: computedResult ] diff --git a/src/GToolkit-GemStone-Pharo/GtGemstoneEvaluationWithExceptionResult.extension.st b/src/GToolkit-GemStone-Pharo/GtGemstoneEvaluationWithExceptionResult.extension.st new file mode 100644 index 00000000..6865aa9d --- /dev/null +++ b/src/GToolkit-GemStone-Pharo/GtGemstoneEvaluationWithExceptionResult.extension.st @@ -0,0 +1,16 @@ +Extension { #name : #GtGemstoneEvaluationWithExceptionResult } + +{ #category : #'*GToolkit-GemStone-Pharo' } +GtGemstoneEvaluationWithExceptionResult >> signalGemStoneDebugger [ + + | exception | + + exception := GtRsrEvaluationException new + debuggerProxy: self evaluationContext. + exception signal. + + ^ exception hasDebugResult + ifTrue: [ GtGemstoneEvaluationWithComputedResult new + computedResult: exception debugResult ] + ifFalse: [ self ] +] diff --git a/src/GToolkit-GemStone-Pharo/GtRsrEvaluatorPromise.class.st b/src/GToolkit-GemStone-Pharo/GtRsrEvaluatorPromise.class.st index 3df9240f..c80ff703 100644 --- a/src/GToolkit-GemStone-Pharo/GtRsrEvaluatorPromise.class.st +++ b/src/GToolkit-GemStone-Pharo/GtRsrEvaluatorPromise.class.st @@ -22,6 +22,13 @@ GtRsrEvaluatorPromise class >> rsrPromise: aPromise serializationStrategy: aSymb sourceEvaluation: aGtRsrEvaluation ] +{ #category : #accessing } +GtRsrEvaluatorPromise >> basicDeserializeResult: aResult [ + ^ (self class environment + at: serializationStrategy) new + deserialize: aResult. +] + { #category : #testing } GtRsrEvaluatorPromise >> canHandleSpecificDebugger [ @@ -30,20 +37,10 @@ GtRsrEvaluatorPromise >> canHandleSpecificDebugger [ { #category : #private } GtRsrEvaluatorPromise >> createEvaluationResultFromData: aDictionaryOrObject [ - "Instantiate an evaluation result object from the given object. - We need to handle the case of the previous way of returning data." - - ^ (GtGemstoneEvaluationResult isSerializedData: aDictionaryOrObject) - ifTrue: [ - GtGemstoneEvaluationResult fromDictionary: aDictionaryOrObject ] - ifFalse: [ - rsrPromise value class = GtpoGtGemStoneEvaluationContext - ifTrue: [ - GtGemstoneEvaluationWithExceptionResult new - evaluationContext: aDictionaryOrObject ] - ifFalse: [ - GtGemstoneEvaluationWithComputedResult new - computedResult:aDictionaryOrObject ] ] + "Instantiate an evaluation result object from the given object." + + ^ GtGemstoneEvaluationResult + createEvaluationResultFromData: aDictionaryOrObject ] { #category : #accessing } @@ -54,9 +51,7 @@ GtRsrEvaluatorPromise >> deserializeResult: aResult [ aGtSession logEmitter emitEvaluationDeserializeResultStartFor: sourceEvaluation ]. - deserializedResult := (self class environment - at: serializationStrategy) new - deserialize: aResult. + deserializedResult := self basicDeserializeResult: aResult. gtSession ifNotNil: [ :aGtSession | aGtSession logEmitter @@ -176,18 +171,18 @@ GtRsrEvaluatorPromise >> wait [ rawEvaluationResultData := rsrPromise wait ]. evaluationResult := self createEvaluationResultFromData: rawEvaluationResultData. - gtSession ifNotNil: [ - evaluationResult gtPharoProxyInitializeWithSession: gtSession ]. + gtSession ifNotNil: [ :aGemStoneSession | + evaluationResult gtPharoProxyInitializeWithSession: aGemStoneSession ]. "Temporarily handle the old post-mortem debugger notification" rawEvaluationResultData class = GtpoGtRsrEvaluationExceptionInformation ifTrue: [ self error: 'Evaluation error, see result' ]. self isGtEvaluationException ifTrue: [ - evaluationResult := self signalGemStoneDebugger ]. + evaluationResult := self signalGemStoneDebugger. + gtSession ifNotNil: [ :aGemStoneSession | + evaluationResult gtPharoProxyInitializeWithSession: aGemStoneSession ]. ]. - gtSession ifNotNil: [ - evaluationResult gtPharoProxyInitializeWithSession: gtSession ]. computedResult := serializationStrategy ifNil: [ evaluationResult computedResult ] ifNotNil: [ diff --git a/src/GToolkit-GemStone-Pharo/GtRsrEvaluatorServiceClient.class.st b/src/GToolkit-GemStone-Pharo/GtRsrEvaluatorServiceClient.class.st index 6e9170c9..eaf9a015 100644 --- a/src/GToolkit-GemStone-Pharo/GtRsrEvaluatorServiceClient.class.st +++ b/src/GToolkit-GemStone-Pharo/GtRsrEvaluatorServiceClient.class.st @@ -59,9 +59,13 @@ GtRsrEvaluatorServiceClient >> evaluateAsyncScript: aGtRsrScriptEvaluation [ bindings: resolvedBindings serializationStrategy: aGtRsrScriptEvaluation serialisationStrategy. + "When making an async call we need to use the legacy serialisation strategy, + as that one is used to get back the data about the remote execution. We could + later on explicitly pass a serialisation strategy to be used for the initial + call that starts the async execution." GtRsrEvaluatorPromise rsrPromise: rsrPromise - serializationStrategy: aGtRsrScriptEvaluation serialisationStrategy + serializationStrategy: #GtRsrLegacySerializationStrategy gtSession: gtSession autoCommit: aGtRsrScriptEvaluation autoCommit sourceEvaluation: aGtRsrScriptEvaluation ] diff --git a/src/GToolkit-GemStone/GtGemstoneEvaluationResult.class.st b/src/GToolkit-GemStone/GtGemstoneEvaluationResult.class.st index a05c71d9..4131aa1b 100644 --- a/src/GToolkit-GemStone/GtGemstoneEvaluationResult.class.st +++ b/src/GToolkit-GemStone/GtGemstoneEvaluationResult.class.st @@ -4,6 +4,23 @@ Class { #category : #'GToolkit-GemStone' } +{ #category : #'instance creation' } +GtGemstoneEvaluationResult class >> createEvaluationResultFromData: aDictionaryOrObject [ + "Instantiate an evaluation result object from the given object. + We need to handle the case of the previous way of returning data." + + ^ (self isSerializedData: aDictionaryOrObject) + ifTrue: [ self fromDictionary: aDictionaryOrObject ] + ifFalse: [ + aDictionaryOrObject class = GtpoGtGemStoneEvaluationContext + ifTrue: [ + GtGemstoneEvaluationWithExceptionResult new + evaluationContext: aDictionaryOrObject ] + ifFalse: [ + GtGemstoneEvaluationWithComputedResult new + computedResult:aDictionaryOrObject ] ] +] + { #category : #'instance creation' } GtGemstoneEvaluationResult class >> fromJSONDictionary: aDictionary [ ^ self new @@ -32,6 +49,11 @@ GtGemstoneEvaluationResult >> computedResult [ ^ self subclassResponsibility ] +{ #category : #testing } +GtGemstoneEvaluationResult >> hasEvaluationException [ + ^ false +] + { #category : #'initialization ' } GtGemstoneEvaluationResult >> initializeFromJSONDictionary: aDictionary [ ] diff --git a/src/GToolkit-GemStone/GtGemstoneEvaluationWithExceptionResult.class.st b/src/GToolkit-GemStone/GtGemstoneEvaluationWithExceptionResult.class.st index 70f80aec..fff839db 100644 --- a/src/GToolkit-GemStone/GtGemstoneEvaluationWithExceptionResult.class.st +++ b/src/GToolkit-GemStone/GtGemstoneEvaluationWithExceptionResult.class.st @@ -7,7 +7,12 @@ Class { #category : #'GToolkit-GemStone' } -{ #category : #'as yet unclassified' } +{ #category : #testing } +GtGemstoneEvaluationWithExceptionResult >> canHandleSpecificDebugger [ + ^ true +] + +{ #category : #accessing } GtGemstoneEvaluationWithExceptionResult >> computedResult [ ^ self evaluationContext ] @@ -27,6 +32,11 @@ GtGemstoneEvaluationWithExceptionResult >> gtPharoProxyInitializeWithSession: aG evaluationContext gtPharoProxyInitializeWithSession: aGemStoneSession ] +{ #category : #testing } +GtGemstoneEvaluationWithExceptionResult >> hasEvaluationException [ + ^ true +] + { #category : #'initialization ' } GtGemstoneEvaluationWithExceptionResult >> initializeFromJSONDictionary: aDictionary [ super initializeFromJSONDictionary: aDictionary.