1- import { produceEffects } from "produceEffects" ;
21import { aggregate } from "../aggregate" ;
32import type { Effect } from "../Effect" ;
43import type { DomainEvent } from "../event-types" ;
4+ import { produceEffects } from "../produceEffects" ;
55import type { Stack } from "../Stack" ;
6+ import { delay } from "../utils/delay" ;
67import type { Publisher } from "../utils/publishers/Publisher" ;
78import type { Scheduler } from "../utils/schedulers/Scheduler" ;
89import type { Aggregator } from "./Aggregator" ;
910
1011export class SyncAggregator implements Aggregator {
1112 private events : DomainEvent [ ] ;
13+ private latestStackSnapshot : Stack ;
1214 private changePublisher : Publisher < { effects : Effect [ ] ; stack : Stack } > ;
1315 private updateScheduler : Scheduler ;
14- private previousStack : Stack ;
1516
16- constructor (
17- events : DomainEvent [ ] ,
18- changePublisher : Publisher < { effects : Effect [ ] ; stack : Stack } > ,
19- updateScheduler : Scheduler ,
20- ) {
21- this . events = events ;
22- this . changePublisher = changePublisher ;
23- this . updateScheduler = updateScheduler ;
24- this . previousStack = this . computeStack ( ) ;
17+ constructor ( options : {
18+ initialEvents : DomainEvent [ ] ;
19+ changePublisher : Publisher < { effects : Effect [ ] ; stack : Stack } > ;
20+ updateScheduler : Scheduler ;
21+ } ) {
22+ this . events = options . initialEvents ;
23+ this . latestStackSnapshot = aggregate ( this . events , Date . now ( ) ) ;
24+ this . changePublisher = options . changePublisher ;
25+ this . updateScheduler = options . updateScheduler ;
2526 }
2627
2728 getStack ( ) : Stack {
28- return this . previousStack ;
29+ return this . latestStackSnapshot ;
2930 }
3031
3132 dispatchEvent ( event : DomainEvent ) : void {
3233 this . events . push ( event ) ;
33- this . updateStack ( ) ;
34+ this . updateSnapshot ( ) ;
3435 }
3536
3637 subscribeChanges (
@@ -41,15 +42,41 @@ export class SyncAggregator implements Aggregator {
4142 } ) ;
4243 }
4344
44- private computeStack ( ) : Stack {
45- return aggregate ( this . events , Date . now ( ) ) ;
45+ private updateSnapshot ( ) : void {
46+ const previousSnapshot = this . latestStackSnapshot ;
47+ const currentSnapshot = aggregate ( this . events , Date . now ( ) ) ;
48+ const effects = produceEffects ( previousSnapshot , currentSnapshot ) ;
49+
50+ if ( effects . length > 0 ) {
51+ this . latestStackSnapshot = currentSnapshot ;
52+ this . changePublisher . publish ( {
53+ effects,
54+ stack : this . latestStackSnapshot ,
55+ } ) ;
56+ }
57+
58+ const earliestUpcomingTransitionStateUpdate =
59+ this . calculateEarliestUpcomingTransitionStateUpdate ( ) ;
60+
61+ if ( earliestUpcomingTransitionStateUpdate ) {
62+ this . updateScheduler . schedule ( async ( options ) => {
63+ await delay (
64+ earliestUpcomingTransitionStateUpdate . timestamp - Date . now ( ) ,
65+ { signal : options ?. signal } ,
66+ ) ;
67+
68+ if ( options ?. signal ?. aborted ) return ;
69+
70+ this . updateSnapshot ( ) ;
71+ } ) ;
72+ }
4673 }
4774
48- private predictUpcomingTransitionStateUpdate ( ) : {
75+ private calculateEarliestUpcomingTransitionStateUpdate ( ) : {
4976 event : DomainEvent ;
5077 timestamp : number ;
5178 } | null {
52- const activeActivities = this . previousStack . activities . filter (
79+ const activeActivities = this . latestStackSnapshot . activities . filter (
5380 ( activity ) =>
5481 activity . transitionState === "enter-active" ||
5582 activity . transitionState === "exit-active" ,
@@ -67,25 +94,4 @@ export class SyncAggregator implements Aggregator {
6794 }
6895 : null ;
6996 }
70-
71- private updateStack ( ) : void {
72- const previousStack = this . previousStack ;
73- const currentStack = this . computeStack ( ) ;
74- const effects = produceEffects ( previousStack , currentStack ) ;
75-
76- if ( effects . length > 0 ) {
77- this . changePublisher . publish ( { effects, stack : currentStack } ) ;
78-
79- this . previousStack = currentStack ;
80-
81- const upcomingTransitionStateUpdate =
82- this . predictUpcomingTransitionStateUpdate ( ) ;
83-
84- if ( upcomingTransitionStateUpdate ) {
85- this . updateScheduler . schedule ( async ( ) => {
86- this . updateStack ( ) ;
87- } ) ;
88- }
89- }
90- }
9197}
0 commit comments