15
15
use std:: { collections:: HashSet , hash:: Hash } ;
16
16
use swimos_agent_protocol:: MapMessage ;
17
17
use swimos_api:: address:: Address ;
18
+ use swimos_form:: Form ;
18
19
use swimos_model:: Text ;
19
20
20
21
use crate :: {
21
22
agent_model:: AgentDescription ,
22
23
downlink_lifecycle:: { OnConsumeEvent , OnFailed , OnLinked , OnSynced , OnUnlinked } ,
23
24
event_handler:: {
24
- ActionContext , AndThen , AndThenContextual , ConstHandler , ContextualTrans , FollowedBy ,
25
- HandlerAction , HandlerActionExt , HandlerTrans , Modification , StepResult ,
25
+ ActionContext , AndThen , AndThenContextual , ConstHandler , ContextualTrans , Described ,
26
+ FollowedBy , HandlerAction , HandlerActionExt , HandlerTrans , Modification , StepResult ,
26
27
} ,
27
28
item:: AgentItem ,
28
29
lanes:: { join:: DownlinkStatus , LinkClosedResponse } ,
@@ -34,7 +35,7 @@ use super::{
34
35
on_failed:: OnJoinMapFailed , on_linked:: OnJoinMapLinked , on_synced:: OnJoinMapSynced ,
35
36
on_unlinked:: OnJoinMapUnlinked ,
36
37
} ,
37
- JoinMapLane ,
38
+ JoinMapAddDownlink , JoinMapLane ,
38
39
} ;
39
40
40
41
#[ cfg( test) ]
@@ -338,13 +339,13 @@ where
338
339
339
340
type OnUnlinkedWithCleanup < ' a , L , K , V , Context , LC > = AndThen <
340
341
<LC as OnJoinMapUnlinked < L , K , Context > >:: OnJoinMapUnlinkedHandler < ' a > ,
341
- AfterClosed < L , K , V , Context > ,
342
- AfterClosedTrans < L , K , V , Context > ,
342
+ AfterClosed < ' a , L , K , V , Context > ,
343
+ AfterClosedTrans < ' a , L , K , V , Context > ,
343
344
> ;
344
345
type OnFailedWithCleanup < ' a , L , K , V , Context , LC > = AndThen <
345
346
<LC as OnJoinMapFailed < L , K , Context > >:: OnJoinMapFailedHandler < ' a > ,
346
- AfterClosed < L , K , V , Context > ,
347
- AfterClosedTrans < L , K , V , Context > ,
347
+ AfterClosed < ' a , L , K , V , Context > ,
348
+ AfterClosedTrans < ' a , L , K , V , Context > ,
348
349
> ;
349
350
350
351
type JoinMapOnUnlinked < ' a , L , K , V , Context , LC > = AndThenContextual <
@@ -361,9 +362,12 @@ type JoinMapOnFailed<'a, L, K, V, Context, LC> = AndThenContextual<
361
362
362
363
impl < L , K , V , LC , Context > OnUnlinked < Context > for JoinMapDownlink < L , K , V , LC , Context >
363
364
where
364
- Context : AgentDescription ,
365
- L : Clone + Hash + Eq + Send ,
366
- K : Clone + Hash + Eq + Send ,
365
+ Context : AgentDescription + ' static ,
366
+ L : Clone + Hash + Eq + Send + ' static ,
367
+ K : Form + Clone + Hash + Ord + Eq + Send + ' static ,
368
+ K :: Rec : Send ,
369
+ V : Form + Send + ' static ,
370
+ V :: BodyRec : Send ,
367
371
LC : OnJoinMapUnlinked < L , K , Context > ,
368
372
{
369
373
type OnUnlinkedHandler < ' a > = JoinMapOnUnlinked < ' a , L , K , V , Context , LC >
@@ -388,9 +392,12 @@ where
388
392
389
393
impl < L , K , V , LC , Context > OnFailed < Context > for JoinMapDownlink < L , K , V , LC , Context >
390
394
where
391
- Context : AgentDescription ,
392
- L : Clone + Hash + Eq + Send ,
393
- K : Clone + Hash + Eq + Send ,
395
+ Context : AgentDescription + ' static ,
396
+ L : Clone + Hash + Eq + Send + ' static ,
397
+ K : Form + Clone + Hash + Ord + Eq + Send + ' static ,
398
+ K :: Rec : Send ,
399
+ V : Form + Send + ' static ,
400
+ V :: BodyRec : Send ,
394
401
LC : OnJoinMapFailed < L , K , Context > ,
395
402
{
396
403
type OnFailedHandler < ' a > = JoinMapOnFailed < ' a , L , K , V , Context , LC >
@@ -456,10 +463,13 @@ impl<'a, L, K, V, Context, LC> RunOnFailedTrans<'a, L, K, V, Context, LC> {
456
463
impl < ' a , L , K , V , Context , LC > ContextualTrans < Context , L >
457
464
for RunOnUnlinkedTrans < ' a , L , K , V , Context , LC >
458
465
where
459
- Context : AgentDescription ,
466
+ Context : AgentDescription + ' static ,
460
467
LC : OnJoinMapUnlinked < L , K , Context > ,
461
- L : Clone + Hash + Eq ,
462
- K : Clone + Hash + Eq ,
468
+ L : Clone + Hash + Eq + Send + ' static ,
469
+ K : Form + Clone + Hash + Ord + Eq + Send + ' static ,
470
+ K :: Rec : Send ,
471
+ V : Form + Send + ' static ,
472
+ V :: BodyRec : Send ,
463
473
{
464
474
type Out = OnUnlinkedWithCleanup < ' a , L , K , V , Context , LC > ;
465
475
@@ -480,6 +490,7 @@ where
480
490
. on_unlinked ( link_key. clone ( ) , remote, keys. clone ( ) )
481
491
. and_then ( AfterClosedTrans {
482
492
projection,
493
+ address : remote_lane,
483
494
link_key,
484
495
keys,
485
496
} )
@@ -489,10 +500,13 @@ where
489
500
impl < ' a , L , K , V , Context , LC > ContextualTrans < Context , L >
490
501
for RunOnFailedTrans < ' a , L , K , V , Context , LC >
491
502
where
492
- Context : AgentDescription ,
503
+ Context : AgentDescription + ' static ,
493
504
LC : OnJoinMapFailed < L , K , Context > ,
494
- L : Clone + Hash + Eq ,
495
- K : Clone + Hash + Eq ,
505
+ L : Clone + Hash + Eq + Send + ' static ,
506
+ K : Form + Clone + Hash + Ord + Eq + Send + ' static ,
507
+ K :: Rec : Send ,
508
+ V : Form + Send + ' static ,
509
+ V :: BodyRec : Send ,
496
510
{
497
511
type Out = OnFailedWithCleanup < ' a , L , K , V , Context , LC > ;
498
512
@@ -513,89 +527,121 @@ where
513
527
. on_failed ( link_key. clone ( ) , remote, keys. clone ( ) )
514
528
. and_then ( AfterClosedTrans {
515
529
projection,
530
+ address : remote_lane,
516
531
link_key,
517
532
keys,
518
533
} )
519
534
}
520
535
}
521
536
522
- pub struct AfterClosedTrans < L , K , V , Context > {
537
+ pub struct AfterClosedTrans < ' a , L , K , V , Context > {
523
538
projection : fn ( & Context ) -> & JoinMapLane < L , K , V > ,
539
+ address : & ' a Address < Text > ,
524
540
link_key : L ,
525
541
keys : HashSet < K > ,
526
542
}
527
543
528
- impl < L , K , V , Context > HandlerTrans < LinkClosedResponse > for AfterClosedTrans < L , K , V , Context > {
529
- type Out = AfterClosed < L , K , V , Context > ;
544
+ impl < ' a , L , K , V , Context > HandlerTrans < LinkClosedResponse >
545
+ for AfterClosedTrans < ' a , L , K , V , Context >
546
+ {
547
+ type Out = AfterClosed < ' a , L , K , V , Context > ;
530
548
531
- fn transform ( self , input : LinkClosedResponse ) -> Self :: Out {
549
+ fn transform ( self , response : LinkClosedResponse ) -> Self :: Out {
532
550
let AfterClosedTrans {
533
551
projection,
552
+ address,
534
553
link_key,
535
554
keys,
536
555
} = self ;
537
- AfterClosed {
556
+ AfterClosed :: Cleanup {
538
557
projection,
558
+ address,
539
559
link_key,
540
- response : Some ( input ) ,
560
+ response,
541
561
keys,
542
562
}
543
563
}
544
564
}
545
565
546
566
/// An event handler that cleans up after a downlink unlinks or fails.
547
- pub struct AfterClosed < L , K , V , Context > {
548
- link_key : L ,
549
- projection : fn ( & Context ) -> & JoinMapLane < L , K , V > ,
550
- response : Option < LinkClosedResponse > ,
551
- keys : HashSet < K > ,
567
+ #[ derive( Default ) ]
568
+ pub enum AfterClosed < ' a , L , K , V , Context > {
569
+ Cleanup {
570
+ link_key : L ,
571
+ projection : fn ( & Context ) -> & JoinMapLane < L , K , V > ,
572
+ address : & ' a Address < Text > ,
573
+ response : LinkClosedResponse ,
574
+ keys : HashSet < K > ,
575
+ } ,
576
+ Restarting ( JoinMapAddDownlink < Context , L , K , V > ) ,
577
+ #[ default]
578
+ Done ,
552
579
}
553
580
554
- impl < L , K , V , Context > HandlerAction < Context > for AfterClosed < L , K , V , Context >
581
+ impl < ' a , L , K , V , Context > HandlerAction < Context > for AfterClosed < ' a , L , K , V , Context >
555
582
where
556
- Context : AgentDescription ,
557
- L : Clone + Hash + Eq ,
558
- K : Clone + Hash + Eq ,
583
+ Context : AgentDescription + ' static ,
584
+ L : Clone + Hash + Eq + Send + ' static ,
585
+ K : Form + Clone + Hash + Ord + Eq + Send + ' static ,
586
+ K :: Rec : Send ,
587
+ V : Form + Send + ' static ,
588
+ V :: BodyRec : Send ,
559
589
{
560
590
type Completion = ( ) ;
561
591
562
592
fn step (
563
593
& mut self ,
564
- _action_context : & mut ActionContext < Context > ,
565
- _meta : AgentMetadata ,
594
+ action_context : & mut ActionContext < Context > ,
595
+ meta : AgentMetadata ,
566
596
context : & Context ,
567
597
) -> StepResult < Self :: Completion > {
568
- let AfterClosed {
569
- link_key,
570
- projection,
571
- response,
572
- keys,
573
- } = self ;
574
- if let Some ( response) = response. take ( ) {
575
- let JoinMapLane {
576
- inner,
577
- link_tracker,
578
- } = projection ( context) ;
579
- link_tracker. borrow_mut ( ) . remove_link ( link_key) ;
580
- match response {
581
- LinkClosedResponse :: Retry => todo ! ( ) ,
582
- LinkClosedResponse :: Abandon => StepResult :: done ( ( ) ) ,
583
- LinkClosedResponse :: Delete => {
584
- if keys. is_empty ( ) {
585
- StepResult :: done ( ( ) )
586
- } else {
587
- for key in keys. iter ( ) {
588
- inner. remove ( key) ;
598
+ loop {
599
+ match std:: mem:: take ( self ) {
600
+ AfterClosed :: Cleanup {
601
+ link_key,
602
+ projection,
603
+ address,
604
+ response,
605
+ keys,
606
+ } => {
607
+ let JoinMapLane {
608
+ inner,
609
+ link_tracker,
610
+ } = projection ( context) ;
611
+ link_tracker. borrow_mut ( ) . remove_link ( & link_key) ;
612
+ match response {
613
+ LinkClosedResponse :: Abandon => break StepResult :: done ( ( ) ) ,
614
+ LinkClosedResponse :: Delete => {
615
+ break if keys. is_empty ( ) {
616
+ StepResult :: done ( ( ) )
617
+ } else {
618
+ for key in keys. iter ( ) {
619
+ inner. remove ( key) ;
620
+ }
621
+ StepResult :: Complete {
622
+ modified_item : Some ( Modification :: of ( inner. id ( ) ) ) ,
623
+ result : ( ) ,
624
+ }
625
+ } ;
589
626
}
590
- StepResult :: Complete {
591
- modified_item : Some ( Modification :: of ( inner. id ( ) ) ) ,
592
- result : ( ) ,
627
+ LinkClosedResponse :: Retry => {
628
+ * self = AfterClosed :: Restarting ( JoinMapAddDownlink :: new (
629
+ projection,
630
+ link_key,
631
+ address. clone ( ) ,
632
+ ) ) ;
593
633
}
594
634
}
595
635
}
636
+ AfterClosed :: Restarting ( mut handler) => {
637
+ let result = handler. step ( action_context, meta, context) ;
638
+ if result. is_cont ( ) {
639
+ * self = AfterClosed :: Restarting ( handler) ;
640
+ }
641
+ break result;
642
+ }
643
+ AfterClosed :: Done => break StepResult :: after_done ( ) ,
596
644
}
597
- } else {
598
- StepResult :: after_done ( )
599
645
}
600
646
}
601
647
@@ -604,17 +650,32 @@ where
604
650
context : & Context ,
605
651
f : & mut std:: fmt:: Formatter < ' _ > ,
606
652
) -> Result < ( ) , std:: fmt:: Error > {
607
- let AfterClosed {
608
- projection,
609
- response,
610
- ..
611
- } = self ;
612
- let lane = ( projection) ( context) ;
613
- let name = context. item_name ( lane. id ( ) ) ;
614
- f. debug_struct ( "AfterClosed" )
615
- . field ( "id" , & lane. id ( ) )
616
- . field ( "lane_name" , & name. as_ref ( ) . map ( |s| s. as_ref ( ) ) )
617
- . field ( "consumed" , & response. is_none ( ) )
618
- . finish ( )
653
+ match self {
654
+ AfterClosed :: Cleanup {
655
+ projection,
656
+ address,
657
+ response,
658
+ ..
659
+ } => {
660
+ let lane = ( projection) ( context) ;
661
+ let name = context. item_name ( lane. id ( ) ) ;
662
+ f. debug_struct ( "AfterClosed" )
663
+ . field ( "state" , & "Cleanup" )
664
+ . field ( "id" , & lane. id ( ) )
665
+ . field ( "lane_name" , & name. as_ref ( ) . map ( |s| s. as_ref ( ) ) )
666
+ . field ( "address" , address)
667
+ . field ( "response" , response)
668
+ . finish ( )
669
+ }
670
+ AfterClosed :: Restarting ( handler) => f
671
+ . debug_struct ( "AfterClosed" )
672
+ . field ( "state" , & "Restarting" )
673
+ . field ( "handler" , & Described :: new ( context, handler) )
674
+ . finish ( ) ,
675
+ AfterClosed :: Done => f
676
+ . debug_struct ( "AfterClosed" )
677
+ . field ( "state" , & "Done" )
678
+ . finish ( ) ,
679
+ }
619
680
}
620
681
}
0 commit comments