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');
|
throw new Error('Syndicate: pendingActions must not be nonempty at start of handleEvent');
|
||||||
}
|
}
|
||||||
this.facets.forEach(function (f) {
|
this.facets.forEach(function (f) {
|
||||||
withCurrentFacet(actor, f, function () { f.handleEvent(e); });
|
withCurrentFacet(actor, f, function () { f.handleEvent(e, false); });
|
||||||
});
|
});
|
||||||
this.quiesce();
|
this.quiesce();
|
||||||
};
|
};
|
||||||
|
@ -160,10 +160,10 @@ function withCurrentFacet(actor, facet, f) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Facet.prototype.handleEvent = function(e) {
|
Facet.prototype.handleEvent = function(e, isSynthetic) {
|
||||||
var facet = this;
|
var facet = this;
|
||||||
facet.endpoints.forEach(function(endpoint) {
|
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 'asserted': /* fall through */
|
||||||
case 'retracted':
|
case 'retracted':
|
||||||
return this.addEndpoint(new Endpoint(subscriptionFn, function(e) {
|
return this.addEndpoint(new Endpoint(subscriptionFn, function(e, isSynthetic) {
|
||||||
if (e.type === 'stateChange') {
|
if (e.type === 'stateChange') {
|
||||||
var proj = projectionFn.call(facet.fields);
|
var proj = projectionFn.call(facet.fields);
|
||||||
var spec = Patch.prependAtMeta(proj.assertion, proj.metalevel);
|
var spec = Patch.prependAtMeta(proj.assertion, proj.metalevel);
|
||||||
|
@ -230,7 +230,7 @@ Facet.prototype.onEvent = function(priority,
|
||||||
var shouldTerminate = isTerminal;
|
var shouldTerminate = isTerminal;
|
||||||
objects.forEach(function (o) {
|
objects.forEach(function (o) {
|
||||||
var instantiated = Trie.instantiateProjection(spec, o);
|
var instantiated = Trie.instantiateProjection(spec, o);
|
||||||
if (facet.interestWas(eventType, instantiated)) {
|
if (facet.interestWas(eventType, instantiated, isSynthetic)) {
|
||||||
if (shouldTerminate) {
|
if (shouldTerminate) {
|
||||||
shouldTerminate = false;
|
shouldTerminate = false;
|
||||||
facet.terminate();
|
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); }
|
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);
|
var newExists = Trie.matchValue(this.actor.knowledge, pat, false, orStar);
|
||||||
switch (assertedOrRetracted) {
|
switch (assertedOrRetracted) {
|
||||||
case 'asserted':
|
case 'asserted':
|
||||||
|
@ -310,7 +311,7 @@ Facet.prototype.completeBuild = function() {
|
||||||
facet.initBlocks.forEach(function(b) { b.call(facet.fields); });
|
facet.initBlocks.forEach(function(b) { b.call(facet.fields); });
|
||||||
});
|
});
|
||||||
var initialEvent = _Dataspace.stateChange(new Patch.Patch(facet.actor.knowledge, Trie.emptyTrie));
|
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() {
|
Facet.prototype.terminate = function() {
|
||||||
|
|
|
@ -397,7 +397,7 @@
|
||||||
(define (on-event* where proc #:priority [priority *normal-priority*])
|
(define (on-event* where proc #:priority [priority *normal-priority*])
|
||||||
(add-endpoint! where
|
(add-endpoint! where
|
||||||
(lambda () patch-empty)
|
(lambda () patch-empty)
|
||||||
(lambda (e)
|
(lambda (e _synthetic?)
|
||||||
(schedule-script! #:priority priority #f (lambda () (proc e))))))
|
(schedule-script! #:priority priority #f (lambda () (proc e))))))
|
||||||
|
|
||||||
(define-syntax (on stx)
|
(define-syntax (on stx)
|
||||||
|
@ -620,19 +620,20 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Syntax-time support
|
;; 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 (or* x y) (or x y))
|
||||||
(define a (current-actor-state))
|
(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*))
|
(define new (trie-lookup (actor-state-knowledge a) pat #f #:wildcard-union or*))
|
||||||
(values old new))
|
(values old new))
|
||||||
|
|
||||||
(define (interest-just-appeared-matching? pat)
|
(define (interest-just-appeared-matching? pat synthetic?)
|
||||||
(define-values (old new) (interests-pre-and-post-patch pat))
|
(define-values (old new) (interests-pre-and-post-patch pat synthetic?))
|
||||||
(and (not old) new))
|
(and (not old) new))
|
||||||
|
|
||||||
(define (interest-just-disappeared-matching? pat)
|
(define (interest-just-disappeared-matching? pat synthetic?)
|
||||||
(define-values (old new) (interests-pre-and-post-patch pat))
|
(define-values (old new) (interests-pre-and-post-patch pat synthetic?))
|
||||||
(and old (not new)))
|
(and old (not new)))
|
||||||
|
|
||||||
(define-for-syntax (analyze-asserted/retracted outer-expr-stx
|
(define-for-syntax (analyze-asserted/retracted outer-expr-stx
|
||||||
|
@ -654,7 +655,7 @@
|
||||||
(lambda () (if #,when-pred-stx
|
(lambda () (if #,when-pred-stx
|
||||||
(core:sub #,pat)
|
(core:sub #,pat)
|
||||||
patch-empty))
|
patch-empty))
|
||||||
(lambda (e)
|
(lambda (e synthetic?)
|
||||||
(core:match-event e
|
(core:match-event e
|
||||||
[(? #,event-predicate-stx p)
|
[(? #,event-predicate-stx p)
|
||||||
(define proj #,proj-stx)
|
(define proj #,proj-stx)
|
||||||
|
@ -670,7 +671,7 @@
|
||||||
#,(let ((entry-handler-stx
|
#,(let ((entry-handler-stx
|
||||||
(quasisyntax/loc script-stx
|
(quasisyntax/loc script-stx
|
||||||
(let ((instantiated (instantiate-projection proj entry)))
|
(let ((instantiated (instantiate-projection proj entry)))
|
||||||
(and (#,change-detector-stx instantiated)
|
(and (#,change-detector-stx instantiated synthetic?)
|
||||||
(schedule-script!
|
(schedule-script!
|
||||||
#:priority #,priority-stx
|
#:priority #,priority-stx
|
||||||
#,(if terminal? #'#t #'#f)
|
#,(if terminal? #'#t #'#f)
|
||||||
|
@ -722,7 +723,7 @@
|
||||||
(lambda () (if #,when-pred-stx
|
(lambda () (if #,when-pred-stx
|
||||||
(core:sub #,pat)
|
(core:sub #,pat)
|
||||||
patch-empty))
|
patch-empty))
|
||||||
(lambda (e)
|
(lambda (e _synthetic?)
|
||||||
(core:match-event e
|
(core:match-event e
|
||||||
[(core:message body)
|
[(core:message body)
|
||||||
(define capture-vals
|
(define capture-vals
|
||||||
|
@ -933,7 +934,8 @@
|
||||||
[field-descriptors (current-field-descriptors)])))))
|
[field-descriptors (current-field-descriptors)])))))
|
||||||
(facet-handle-event! fid
|
(facet-handle-event! fid
|
||||||
(lookup-facet 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)))
|
(when (and (facet-live? fid) parent-fid (not (facet-live? parent-fid)))
|
||||||
(terminate-facet! fid)))
|
(terminate-facet! fid)))
|
||||||
|
|
||||||
|
@ -1067,13 +1069,13 @@
|
||||||
(current-pending-actions '())
|
(current-pending-actions '())
|
||||||
(current-pending-scripts (make-empty-pending-scripts))]
|
(current-pending-scripts (make-empty-pending-scripts))]
|
||||||
(for [((fid f) (in-hash (actor-state-facets a)))]
|
(for [((fid f) (in-hash (actor-state-facets a)))]
|
||||||
(facet-handle-event! fid f e))
|
(facet-handle-event! fid f e #f))
|
||||||
(run-scripts!))))
|
(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
|
(with-current-facet fid (facet-field-descriptors f) #f
|
||||||
(for [(ep (in-hash-values (facet-endpoints f)))]
|
(for [(ep (in-hash-values (facet-endpoints f)))]
|
||||||
((endpoint-handler-fn ep) e))))
|
((endpoint-handler-fn ep) e synthetic?))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Script suspend-and-resume.
|
;; 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