Treat synthetic patches differently wrt previousKnowledge
This commit is contained in:
parent
cd754be396
commit
eaade6e4fd
|
@ -70,7 +70,7 @@ Actor.prototype.handleEvent = function(e) {
|
|||
throw new Error('Syndicate: pendingActions must not be nonempty at start of handleEvent');
|
||||
}
|
||||
this.facets.forEach(function (f) {
|
||||
withCurrentFacet(actor, f, function () { f.handleEvent(e); });
|
||||
withCurrentFacet(actor, f, function () { f.handleEvent(e, false); });
|
||||
});
|
||||
this.quiesce();
|
||||
};
|
||||
|
@ -160,10 +160,10 @@ function withCurrentFacet(actor, facet, f) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Facet.prototype.handleEvent = function(e) {
|
||||
Facet.prototype.handleEvent = function(e, isSynthetic) {
|
||||
var facet = this;
|
||||
facet.endpoints.forEach(function(endpoint) {
|
||||
endpoint.handlerFn.call(facet.fields, e);
|
||||
endpoint.handlerFn.call(facet.fields, e, isSynthetic);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -218,7 +218,7 @@ Facet.prototype.onEvent = function(priority,
|
|||
|
||||
case 'asserted': /* fall through */
|
||||
case 'retracted':
|
||||
return this.addEndpoint(new Endpoint(subscriptionFn, function(e) {
|
||||
return this.addEndpoint(new Endpoint(subscriptionFn, function(e, isSynthetic) {
|
||||
if (e.type === 'stateChange') {
|
||||
var proj = projectionFn.call(facet.fields);
|
||||
var spec = Patch.prependAtMeta(proj.assertion, proj.metalevel);
|
||||
|
@ -230,7 +230,7 @@ Facet.prototype.onEvent = function(priority,
|
|||
var shouldTerminate = isTerminal;
|
||||
objects.forEach(function (o) {
|
||||
var instantiated = Trie.instantiateProjection(spec, o);
|
||||
if (facet.interestWas(eventType, instantiated)) {
|
||||
if (facet.interestWas(eventType, instantiated, isSynthetic)) {
|
||||
if (shouldTerminate) {
|
||||
shouldTerminate = false;
|
||||
facet.terminate();
|
||||
|
@ -264,9 +264,10 @@ Facet.prototype.onEvent = function(priority,
|
|||
}
|
||||
};
|
||||
|
||||
Facet.prototype.interestWas = function(assertedOrRetracted, pat) {
|
||||
Facet.prototype.interestWas = function(assertedOrRetracted, pat, isSyntheticEvent) {
|
||||
function orStar(a, b) { return (a || b); }
|
||||
var oldExists = Trie.matchValue(this.actor.previousKnowledge, pat, false, orStar);
|
||||
var previousKnowledge = isSyntheticEvent ? Trie.emptyTrie : this.actor.previousKnowledge;
|
||||
var oldExists = Trie.matchValue(previousKnowledge, pat, false, orStar);
|
||||
var newExists = Trie.matchValue(this.actor.knowledge, pat, false, orStar);
|
||||
switch (assertedOrRetracted) {
|
||||
case 'asserted':
|
||||
|
@ -310,7 +311,7 @@ Facet.prototype.completeBuild = function() {
|
|||
facet.initBlocks.forEach(function(b) { b.call(facet.fields); });
|
||||
});
|
||||
var initialEvent = _Dataspace.stateChange(new Patch.Patch(facet.actor.knowledge, Trie.emptyTrie));
|
||||
withCurrentFacet(this.actor, facet, function () { facet.handleEvent(initialEvent); });
|
||||
withCurrentFacet(this.actor, facet, function () { facet.handleEvent(initialEvent, true); });
|
||||
};
|
||||
|
||||
Facet.prototype.terminate = function() {
|
||||
|
|
|
@ -397,7 +397,7 @@
|
|||
(define (on-event* where proc #:priority [priority *normal-priority*])
|
||||
(add-endpoint! where
|
||||
(lambda () patch-empty)
|
||||
(lambda (e)
|
||||
(lambda (e _synthetic?)
|
||||
(schedule-script! #:priority priority #f (lambda () (proc e))))))
|
||||
|
||||
(define-syntax (on stx)
|
||||
|
@ -620,19 +620,20 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Syntax-time support
|
||||
|
||||
(define (interests-pre-and-post-patch pat)
|
||||
(define (interests-pre-and-post-patch pat synthetic?)
|
||||
(define (or* x y) (or x y))
|
||||
(define a (current-actor-state))
|
||||
(define old (trie-lookup (actor-state-previous-knowledge a) pat #f #:wildcard-union or*))
|
||||
(define previous-knowledge (if synthetic? trie-empty (actor-state-previous-knowledge a)))
|
||||
(define old (trie-lookup previous-knowledge pat #f #:wildcard-union or*))
|
||||
(define new (trie-lookup (actor-state-knowledge a) pat #f #:wildcard-union or*))
|
||||
(values old new))
|
||||
|
||||
(define (interest-just-appeared-matching? pat)
|
||||
(define-values (old new) (interests-pre-and-post-patch pat))
|
||||
(define (interest-just-appeared-matching? pat synthetic?)
|
||||
(define-values (old new) (interests-pre-and-post-patch pat synthetic?))
|
||||
(and (not old) new))
|
||||
|
||||
(define (interest-just-disappeared-matching? pat)
|
||||
(define-values (old new) (interests-pre-and-post-patch pat))
|
||||
(define (interest-just-disappeared-matching? pat synthetic?)
|
||||
(define-values (old new) (interests-pre-and-post-patch pat synthetic?))
|
||||
(and old (not new)))
|
||||
|
||||
(define-for-syntax (analyze-asserted/retracted outer-expr-stx
|
||||
|
@ -654,7 +655,7 @@
|
|||
(lambda () (if #,when-pred-stx
|
||||
(core:sub #,pat)
|
||||
patch-empty))
|
||||
(lambda (e)
|
||||
(lambda (e synthetic?)
|
||||
(core:match-event e
|
||||
[(? #,event-predicate-stx p)
|
||||
(define proj #,proj-stx)
|
||||
|
@ -670,7 +671,7 @@
|
|||
#,(let ((entry-handler-stx
|
||||
(quasisyntax/loc script-stx
|
||||
(let ((instantiated (instantiate-projection proj entry)))
|
||||
(and (#,change-detector-stx instantiated)
|
||||
(and (#,change-detector-stx instantiated synthetic?)
|
||||
(schedule-script!
|
||||
#:priority #,priority-stx
|
||||
#,(if terminal? #'#t #'#f)
|
||||
|
@ -722,7 +723,7 @@
|
|||
(lambda () (if #,when-pred-stx
|
||||
(core:sub #,pat)
|
||||
patch-empty))
|
||||
(lambda (e)
|
||||
(lambda (e _synthetic?)
|
||||
(core:match-event e
|
||||
[(core:message body)
|
||||
(define capture-vals
|
||||
|
@ -933,7 +934,8 @@
|
|||
[field-descriptors (current-field-descriptors)])))))
|
||||
(facet-handle-event! fid
|
||||
(lookup-facet fid)
|
||||
(patch (actor-state-knowledge (current-actor-state)) trie-empty))
|
||||
(patch (actor-state-knowledge (current-actor-state)) trie-empty)
|
||||
#t)
|
||||
(when (and (facet-live? fid) parent-fid (not (facet-live? parent-fid)))
|
||||
(terminate-facet! fid)))
|
||||
|
||||
|
@ -1067,13 +1069,13 @@
|
|||
(current-pending-actions '())
|
||||
(current-pending-scripts (make-empty-pending-scripts))]
|
||||
(for [((fid f) (in-hash (actor-state-facets a)))]
|
||||
(facet-handle-event! fid f e))
|
||||
(facet-handle-event! fid f e #f))
|
||||
(run-scripts!))))
|
||||
|
||||
(define (facet-handle-event! fid f e)
|
||||
(define (facet-handle-event! fid f e synthetic?)
|
||||
(with-current-facet fid (facet-field-descriptors f) #f
|
||||
(for [(ep (in-hash-values (facet-endpoints f)))]
|
||||
((endpoint-handler-fn ep) e))))
|
||||
((endpoint-handler-fn ep) e synthetic?))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Script suspend-and-resume.
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#lang syndicate/actor
|
||||
;; Illustrates a (now fixed) bug where creating a facet interested in something
|
||||
;; already known didn't properly trigger the assertion-handler.
|
||||
;;
|
||||
;; Symptomatic output:
|
||||
;;
|
||||
;; +outer "first"
|
||||
;; +show
|
||||
;; -show
|
||||
;; -outer "first"
|
||||
;; +outer "second"
|
||||
;;
|
||||
;; Correct output:
|
||||
;;
|
||||
;; +outer "first"
|
||||
;; +show
|
||||
;; -show
|
||||
;; -outer "first"
|
||||
;; +outer "second"
|
||||
;; +show
|
||||
;;
|
||||
;; Should eventually be turned into some kind of test case.
|
||||
|
||||
(struct outer (v) #:prefab)
|
||||
(struct show () #:prefab)
|
||||
|
||||
(actor (react (field [v "first"])
|
||||
(assert (outer (v)))
|
||||
(assert (show))
|
||||
(on (message 2)
|
||||
(v "second"))))
|
||||
|
||||
(actor (react (on-start (send! 1))
|
||||
(during (outer $v)
|
||||
(on-start (log-info "+outer ~v" v))
|
||||
(on-stop (log-info "-outer ~v" v))
|
||||
(during (show)
|
||||
(on-start (log-info "+show"))
|
||||
(on-stop (log-info "-show"))))
|
||||
(on (message 1)
|
||||
(send! 2))))
|
Loading…
Reference in New Issue