kameo 0.20.0

Fault-tolerant Async Actors Built on Tokio
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
//! Core functionality for defining and managing actors in Kameo.
//!
//! Actors are independent units of computation that run asynchronously, sending and receiving messages.
//! Each actor operates within its own task, and its lifecycle is managed by hooks such as `on_start`, `on_panic`, and `on_stop`.
//!
//! The actor trait is designed to support fault tolerance, recovery from panics, and clean termination.
//! Lifecycle hooks allow customization of actor behavior when starting, encountering errors, or shutting down.
//!
//! This module contains the primary `Actor` trait, which all actors must implement,
//! as well as types for managing message queues (mailboxes) and actor references ([`ActorRef`]).
//!
//! # Features
//! - **Asynchronous Message Handling**: Each actor processes messages asynchronously within its own task.
//! - **Lifecycle Hooks**: Customizable hooks ([`on_start`], [`on_stop`], [`on_panic`]) for managing the actor's lifecycle.
//! - **Backpressure**: Mailboxes can be bounded or unbounded, controlling the flow of messages.
//! - **Supervision**: Actors can be linked, enabling robust supervision and error recovery systems.
//!
//! This module allows building resilient, fault-tolerant, distributed systems with flexible control over the actor lifecycle.
//!
//! [`on_start`]: Actor::on_start
//! [`on_stop`]: Actor::on_stop
//! [`on_panic`]: Actor::on_panic

mod actor_ref;
mod id;
mod kind;
mod spawn;

use std::{any, ops::ControlFlow};

use futures::Future;

use crate::{
    error::{ActorStopReason, PanicError},
    mailbox::{self, MailboxReceiver, MailboxSender, Signal},
    message::BoxMessage,
    reply::{BoxReplySender, ReplyError},
    supervision::{SupervisedActorBuilder, SupervisionStrategy},
};

pub use actor_ref::*;
pub use id::*;
pub use spawn::*;

pub(crate) const DEFAULT_MAILBOX_CAPACITY: usize = 64;

/// Core behavior of an actor, including its lifecycle events and how it processes messages.
///
/// Every actor must implement this trait, which provides hooks
/// for the actor's initialization ([`on_start`]), handling errors ([`on_panic`]), and cleanup ([`on_stop`]).
///
/// The actor runs within its own task and processes messages asynchronously from a mailbox.
/// Each actor can be linked to others, allowing for robust supervision and failure recovery mechanisms.
///
/// Methods in this trait that return [`Self::Error`] will cause the actor to stop with the reason
/// [`ActorStopReason::Panicked`] if an error occurs. This enables graceful handling of actor panics
/// or errors.
///
/// # Example with Derive
///
/// ```
/// use kameo::Actor;
///
/// #[derive(Actor)]
/// struct MyActor;
/// ```
///
/// # Example Override Behaviour
///
/// ```
/// use kameo::actor::{Actor, ActorRef, WeakActorRef};
/// use kameo::error::{ActorStopReason, Infallible};
///
/// struct MyActor;
///
/// impl Actor for MyActor {
///     type Args = Self;
///     type Error = Infallible;
///
///     async fn on_start(
///         state: Self::Args,
///         actor_ref: ActorRef<Self>
///     ) -> Result<Self, Self::Error> {
///         println!("actor started");
///         Ok(state)
///     }
///
///     async fn on_stop(
///         &mut self,
///         actor_ref: WeakActorRef<Self>,
///         reason: ActorStopReason,
///     ) -> Result<(), Self::Error> {
///         println!("actor stopped");
///         Ok(())
///     }
/// }
/// ```
///
/// # Lifecycle Hooks
/// - [`on_start`]: Called when the actor starts. This is where initialization happens.
/// - [`on_panic`]: Called when the actor encounters a panic or an error while processing a "tell" message.
/// - [`on_stop`]: Called before the actor is stopped. This allows for cleanup tasks.
/// - [`on_link_died`]: Hook that is invoked when a linked actor dies.
///
/// # Mailboxes
/// Actors use a mailbox to queue incoming messages. You can choose between:
/// - **Bounded Mailbox**: Limits the number of messages that can be queued, providing backpressure.
/// - **Unbounded Mailbox**: Allows an infinite number of messages, but can lead to high memory usage.
///
/// Mailboxes enable efficient asynchronous message passing with support for both backpressure and
/// unbounded queueing depending on system requirements.
///
/// [`on_start`]: Actor::on_start
/// [`on_panic`]: Actor::on_panic
/// [`on_stop`]: Actor::on_stop
/// [`on_link_died`]: Actor::on_link_died
pub trait Actor: Sized + Send + 'static {
    /// Arguments to initialize the actor.
    ///
    /// Its common for `Args = Self`, allowing the actors state to be passed directly,
    /// however for more complex use cases, the args can be any other type.
    type Args: Send;

    /// Actor error type.
    ///
    /// This error is used as the error returned by lifecycle hooks in this actor.
    type Error: ReplyError;

    /// The name of the actor, which can be useful for logging or debugging.
    ///
    /// # Default Implementation
    /// By default, this returns the type name of the actor.
    #[inline]
    fn name() -> &'static str {
        any::type_name::<Self>()
    }

    /// Defines the supervision strategy for this actor when acting as a supervisor.
    ///
    /// The supervision strategy determines which children should be restarted when a child
    /// actor fails. Override this method to customize the behavior.
    ///
    /// # Default
    ///
    /// [`SupervisionStrategy::OneForOne`] - only restart the failed child
    ///
    /// # When to Override
    ///
    /// - Use [`SupervisionStrategy::OneForAll`] when children are tightly coupled and must be
    ///   kept in sync (e.g., services that share distributed state)
    /// - Use [`SupervisionStrategy::RestForOne`] when children have sequential dependencies
    ///   (e.g., pipeline stages where later stages depend on earlier ones)
    ///
    /// # Examples
    ///
    /// ```
    /// use kameo::actor::{Actor, ActorRef};
    /// use kameo::error::Infallible;
    /// use kameo::supervision::SupervisionStrategy;
    ///
    /// struct Supervisor;
    ///
    /// impl Actor for Supervisor {
    ///     type Args = ();
    ///     type Error = Infallible;
    ///
    ///     // Override to use OneForAll strategy
    ///     fn supervision_strategy() -> SupervisionStrategy {
    ///         SupervisionStrategy::OneForAll
    ///     }
    ///
    ///     async fn on_start(
    ///         _: Self::Args,
    ///         _: ActorRef<Self>
    ///     ) -> Result<Self, Self::Error> {
    ///         Ok(Supervisor)
    ///     }
    /// }
    /// ```
    ///
    /// [`SupervisionStrategy::OneForOne`]: crate::supervision::SupervisionStrategy::OneForOne
    /// [`SupervisionStrategy::OneForAll`]: crate::supervision::SupervisionStrategy::OneForAll
    /// [`SupervisionStrategy::RestForOne`]: crate::supervision::SupervisionStrategy::RestForOne
    #[inline]
    fn supervision_strategy() -> SupervisionStrategy {
        SupervisionStrategy::default()
    }

    /// Called when the actor starts, before it processes any messages.
    ///
    /// Messages sent internally by the actor during `on_start` are prioritized and processed
    /// before any externally sent messages, even if external messages are received first.
    ///
    /// This ensures that the actor can properly initialize before handling external messages.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use kameo::actor::{Actor, ActorRef};
    /// # use kameo::error::Infallible;
    /// #
    /// struct MyActor;
    ///
    /// impl Actor for MyActor {
    ///     type Args = Self;
    ///     type Error = Infallible;
    ///
    ///     async fn on_start(
    ///         state: Self::Args,
    ///         _actor_ref: ActorRef<Self>
    ///     ) -> Result<Self, Self::Error> {
    ///         Ok(state)
    ///     }
    /// }
    /// ```
    #[allow(unused_variables)]
    fn on_start(
        args: Self::Args,
        actor_ref: ActorRef<Self>,
    ) -> impl Future<Output = Result<Self, Self::Error>> + Send;

    /// Called when the actor receives a message to be processed.
    ///
    /// By default, this method handles the incoming message immediately using the
    /// actor's standard message handling logic.
    ///
    /// Advanced use cases can override this method to customize how messages are processed,
    /// such as buffering messages for later processing or implementing custom scheduling.
    ///
    /// # Parameters
    /// - `msg`: The incoming message, wrapped in a `BoxMessage<Self>`.
    /// - `actor_ref`: A reference to the actor itself.
    /// - `tx`: An optional reply sender, used when the message expects a response.
    /// - `stop`: A mutable bool which can be set to true, stopping the actor immediately after processing this message.
    ///
    /// # Returns
    /// A future that resolves to `Result<(), Box<dyn ReplyError>>`. An `Ok(())` indicates successful processing,
    /// while an `Err` indicates an error occurred during message handling.
    ///
    /// # Default Implementation
    /// The default implementation handles the message immediately by calling
    /// `msg.handle_dyn(self, actor_ref, tx).await`.
    ///
    /// # Notes
    /// - Overriding this method allows you to intercept and manipulate messages before they are processed.
    /// - Be cautious when buffering messages, as unbounded buffering can lead to increased memory usage.
    /// - Custom implementations should ensure that messages are eventually handled or appropriately discarded to
    ///   prevent message loss.
    /// - The `tx` (reply sender) is tied to the specific `BoxMessage` it corresponds to,
    ///   and passing an incorrect or mismatched `tx` can lead to a panic.
    /// - The `stop` variable can be set to true in a message handler, by calling `Context::stop`.
    fn on_message(
        &mut self,
        msg: BoxMessage<Self>,
        actor_ref: ActorRef<Self>,
        tx: Option<BoxReplySender>,
        stop: &mut bool,
    ) -> impl Future<Output = Result<(), Box<dyn ReplyError>>> + Send {
        async move { msg.handle_dyn(self, actor_ref, tx, stop).await }
    }

    /// Called when the actor encounters a panic or an error during "tell" message handling.
    ///
    /// This method gives the actor an opportunity to clean up or reset its state and determine
    /// whether it should be stopped or continue processing messages.
    ///
    /// The `PanicError` parameter holds the error that occurred during.
    /// This error can typically be downcasted into one of a few types:
    /// - [`Self::Error`] type, which is the error type when one of the actor's lifecycle functions returns an error.
    /// - An error type returned when handling a message.
    /// - A string type, which can be accessed with `PanicError::with_str`.
    ///   String types are the result of regular panics, typically raised using the [`std::panic!`] macro.
    /// - Any other panic types. Typically uncommon, though possible with [`std::panic::panic_any`].
    ///
    /// # Returns
    /// Whether the actor should stop or continue processing messages.
    #[allow(unused_variables)]
    #[inline]
    fn on_panic(
        &mut self,
        actor_ref: WeakActorRef<Self>,
        err: PanicError,
    ) -> impl Future<Output = Result<ControlFlow<ActorStopReason>, Self::Error>> + Send {
        async move { Ok(ControlFlow::Break(ActorStopReason::Panicked(err))) }
    }

    /// Called when a linked actor dies.
    ///
    /// By default, the actor will stop if the reason for the linked actor's death is anything other
    /// than `Normal`. You can customize this behavior in the implementation.
    ///
    /// # Returns
    /// Whether the actor should stop or continue processing messages.
    #[allow(unused_variables)]
    #[inline]
    fn on_link_died(
        &mut self,
        actor_ref: WeakActorRef<Self>,
        id: ActorId,
        reason: ActorStopReason,
    ) -> impl Future<Output = Result<ControlFlow<ActorStopReason>, Self::Error>> + Send {
        async move {
            match &reason {
                ActorStopReason::Normal | ActorStopReason::SupervisorRestart => {
                    Ok(ControlFlow::Continue(()))
                }
                ActorStopReason::Killed
                | ActorStopReason::Panicked(_)
                | ActorStopReason::LinkDied { .. } => {
                    Ok(ControlFlow::Break(ActorStopReason::LinkDied {
                        id,
                        reason: Box::new(reason),
                    }))
                }
                #[cfg(feature = "remote")]
                ActorStopReason::PeerDisconnected => {
                    Ok(ControlFlow::Break(ActorStopReason::PeerDisconnected))
                }
            }
        }
    }

    /// Called before the actor stops.
    ///
    /// This allows the actor to perform any necessary cleanup or release resources before being fully stopped.
    ///
    /// The error returned by this method will be unwraped by kameo, causing a panic in the tokio task or
    /// thread running the actor.
    #[allow(unused_variables)]
    #[inline]
    fn on_stop(
        &mut self,
        actor_ref: WeakActorRef<Self>,
        reason: ActorStopReason,
    ) -> impl Future<Output = Result<(), Self::Error>> + Send {
        async { Ok(()) }
    }

    /// Awaits the next signal typically from the mailbox.
    ///
    /// This can be overwritten for more advanced actor behaviour, such as awaiting multiple channels, etc.
    /// The return value is a signal which will be handled by the actor.
    #[allow(unused_variables)]
    #[inline]
    fn next(
        &mut self,
        actor_ref: WeakActorRef<Self>,
        mailbox_rx: &mut MailboxReceiver<Self>,
    ) -> impl Future<Output = Result<Option<Signal<Self>>, Self::Error>> + Send {
        async move { Ok(mailbox_rx.recv().await) }
    }
}

/// Provides methods for spawning actors with various configurations.
///
/// This trait is automatically implemented for all types that implement [`Actor`], providing
/// convenient methods to spawn actors in different execution contexts and with different
/// mailbox configurations.
///
/// The `Spawn` trait separates actor instantiation from actor behavior, keeping the [`Actor`]
/// trait focused on lifecycle hooks and message handling while providing ergonomic spawn
/// methods through this extension trait.
///
/// # Choosing a Spawn Method
///
/// - **[`spawn`]** or **[`spawn_default`]**: Standard async actor with bounded mailbox (most common)
/// - **[`spawn_with_mailbox`]**: Custom mailbox configuration (unbounded, custom capacity)
/// - **[`spawn_in_thread`]**: Blocking operations requiring dedicated thread
/// - **[`spawn_link`]**: Actor needs supervision link established before spawning
///
/// # Examples
///
/// ## Basic Spawning
///
/// ```
/// use kameo::Actor;
/// use kameo::actor::Spawn;
///
/// #[derive(Actor)]
/// struct Counter {
///     count: i32,
/// }
///
/// # tokio_test::block_on(async {
/// // Spawn with explicit initialization
/// let actor_ref = Counter::spawn(Counter { count: 0 });
/// # })
/// ```
///
/// ## Default Spawning
///
/// ```
/// use kameo::Actor;
/// use kameo::actor::Spawn;
///
/// #[derive(Actor, Default)]
/// struct Counter {
///     count: i32,
/// }
///
/// # tokio_test::block_on(async {
/// // Spawn with default initialization
/// let actor_ref = Counter::spawn_default();
/// # })
/// ```
///
/// ## Custom Mailbox
///
/// ```
/// use kameo::Actor;
/// use kameo::actor::Spawn;
/// use kameo::mailbox;
///
/// #[derive(Actor)]
/// struct HighThroughput;
///
/// # tokio_test::block_on(async {
/// // Spawn with unbounded mailbox for high message rates
/// let actor_ref = HighThroughput::spawn_with_mailbox(
///     HighThroughput,
///     mailbox::unbounded()
/// );
/// # })
/// ```
///
/// ## Blocking Operations
///
/// ```no_run
/// use std::fs::File;
/// use kameo::Actor;
/// use kameo::actor::Spawn;
///
/// #[derive(Actor)]
/// struct FileWriter {
///     file: File,
/// }
///
/// // Spawn in dedicated thread for blocking I/O
/// let actor_ref = FileWriter::spawn_in_thread(
///     FileWriter { file: File::create("log.txt").unwrap() }
/// );
/// ```
///
/// ## Supervision
///
/// ```
/// use kameo::Actor;
/// use kameo::actor::Spawn;
///
/// #[derive(Actor)]
/// struct Supervisor;
///
/// #[derive(Actor)]
/// struct Worker;
///
/// # tokio_test::block_on(async {
/// let supervisor = Supervisor::spawn(Supervisor);
/// // Link worker to supervisor before spawning
/// let worker = Worker::spawn_link(&supervisor, Worker).await;
/// # })
/// ```
///
/// # Note
///
/// This trait is sealed and cannot be implemented manually. It is automatically available
/// for all [`Actor`] types through a blanket implementation.
///
/// [`spawn`]: Spawn::spawn
/// [`spawn_default`]: Spawn::spawn_default
/// [`spawn_with_mailbox`]: Spawn::spawn_with_mailbox
/// [`spawn_in_thread`]: Spawn::spawn_in_thread
/// [`spawn_link`]: Spawn::spawn_link
pub trait Spawn: Actor + private::Sealed {
    /// Spawns the actor in a Tokio task, running asynchronously with a default bounded mailbox.
    ///
    /// This function spawns the actor in a non-blocking Tokio task, making it suitable for actors that need to
    /// perform asynchronous operations. The actor runs in the background and can be interacted with through
    /// the returned [`ActorRef`].
    ///
    /// By default, a bounded mailbox with capacity 64 is used to provide backpressure.
    /// For custom mailbox configuration, use [`Spawn::spawn_with_mailbox`].
    ///
    /// # Example
    ///
    /// ```
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    ///
    /// #[derive(Actor)]
    /// struct MyActor;
    ///
    /// # tokio_test::block_on(async {
    /// // Spawns with a default bounded mailbox (capacity 64)
    /// let actor_ref = MyActor::spawn(MyActor);
    /// # })
    /// ```
    ///
    /// The actor will continue running in the background, and messages can be sent to it via `actor_ref`.
    fn spawn(args: Self::Args) -> ActorRef<Self> {
        Spawn::spawn_with_mailbox(args, mailbox::bounded(DEFAULT_MAILBOX_CAPACITY))
    }

    /// Spawns the actor with default initialization in a Tokio task.
    ///
    /// This is a convenience method for actors that implement [`Default`], equivalent to calling
    /// `Self::spawn(Self::default())`. The actor runs asynchronously in a non-blocking Tokio task
    /// and can be interacted with through the returned [`ActorRef`].
    ///
    /// By default, a bounded mailbox with capacity 64 is used to provide backpressure.
    /// For custom initialization or mailbox configuration, use [`Spawn::spawn`] or
    /// [`Spawn::spawn_with_mailbox`] instead.
    ///
    /// # Example
    ///
    /// ```
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    ///
    /// #[derive(Actor, Default)]
    /// struct MyActor {
    ///     count: i32,
    /// }
    ///
    /// # tokio_test::block_on(async {
    /// // Spawns with default state and bounded mailbox (capacity 64)
    /// let actor_ref = MyActor::spawn_default();
    /// # })
    /// ```
    ///
    /// # Requirements
    ///
    /// This method requires that `Self::Args` implements [`Default`]. For actors where
    /// `Args = Self`, this means the actor struct itself must implement `Default`.
    #[must_use]
    fn spawn_default() -> ActorRef<Self>
    where
        Self::Args: Default,
    {
        Spawn::spawn(Self::Args::default())
    }

    /// Spawns the actor in a Tokio task with a specific mailbox configuration.
    ///
    /// This function allows you to explicitly specify a mailbox when spawning an actor.
    /// Use this when you need custom mailbox behavior or capacity.
    ///
    /// # Example
    ///
    /// ```
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    /// use kameo::mailbox;
    ///
    /// #[derive(Actor)]
    /// struct MyActor;
    ///
    /// # tokio_test::block_on(async {
    /// // Using a bounded mailbox with custom capacity
    /// let actor_ref = MyActor::spawn_with_mailbox(MyActor, mailbox::bounded(1000));
    ///
    /// // Using an unbounded mailbox
    /// let actor_ref = MyActor::spawn_with_mailbox(MyActor, mailbox::unbounded());
    /// # })
    /// ```
    fn spawn_with_mailbox(
        args: Self::Args,
        (mailbox_tx, mailbox_rx): (MailboxSender<Self>, MailboxReceiver<Self>),
    ) -> ActorRef<Self> {
        let prepared_actor = PreparedActor::new((mailbox_tx, mailbox_rx));
        let actor_ref = prepared_actor.actor_ref().clone();
        prepared_actor.spawn(args);
        actor_ref
    }

    /// Spawns and links the actor in a Tokio task with a default bounded mailbox.
    ///
    /// This function is used to ensure an actor is linked with another actor before it's truly spawned,
    /// which avoids possible edge cases where the actor could die before having the chance to be linked.
    ///
    /// By default, a bounded mailbox with capacity 64 is used to provide backpressure.
    /// For custom mailbox configuration, use [`Spawn::spawn_link_with_mailbox`].
    ///
    /// # Example
    ///
    /// ```
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    ///
    /// #[derive(Actor)]
    /// struct FooActor;
    ///
    /// #[derive(Actor)]
    /// struct BarActor;
    ///
    /// # tokio_test::block_on(async {
    /// let link_ref = FooActor::spawn(FooActor);
    /// // Spawns with default bounded mailbox (capacity 64)
    /// let actor_ref = BarActor::spawn_link(&link_ref, BarActor).await;
    /// # })
    /// ```
    fn spawn_link<L>(
        link_ref: &ActorRef<L>,
        args: Self::Args,
    ) -> impl Future<Output = ActorRef<Self>> + Send
    where
        L: Actor,
    {
        <Self as Spawn>::spawn_link_with_mailbox::<L>(
            link_ref,
            args,
            mailbox::bounded(DEFAULT_MAILBOX_CAPACITY),
        )
    }

    /// Spawns and links the actor in a Tokio task with a specific mailbox configuration.
    ///
    /// This function is used to ensure an actor is linked with another actor before it's truly spawned,
    /// which avoids possible edge cases where the actor could die before having the chance to be linked.
    ///
    /// # Example
    ///
    /// ```
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    /// use kameo::mailbox;
    ///
    /// #[derive(Actor)]
    /// struct FooActor;
    ///
    /// #[derive(Actor)]
    /// struct BarActor;
    ///
    /// # tokio_test::block_on(async {
    /// let link_ref = FooActor::spawn(FooActor);
    /// // Using a custom mailbox
    /// let actor_ref = BarActor::spawn_link_with_mailbox(&link_ref, BarActor, mailbox::unbounded()).await;
    /// # })
    /// ```
    fn spawn_link_with_mailbox<L>(
        link_ref: &ActorRef<L>,
        args: Self::Args,
        (mailbox_tx, mailbox_rx): (MailboxSender<Self>, MailboxReceiver<Self>),
    ) -> impl Future<Output = ActorRef<Self>> + Send
    where
        L: Actor,
    {
        async move {
            let prepared_actor = PreparedActor::new((mailbox_tx, mailbox_rx));
            let actor_ref = prepared_actor.actor_ref().clone();
            actor_ref.link(link_ref).await;
            prepared_actor.spawn(args);
            actor_ref
        }
    }

    /// Spawns the actor in its own dedicated thread with a default bounded mailbox.
    ///
    /// This function spawns the actor in a separate thread, making it suitable for actors that perform blocking
    /// operations, such as file I/O or other tasks that cannot be efficiently executed in an asynchronous context.
    /// Despite running in a blocking thread, the actor can still communicate asynchronously with other actors.
    ///
    /// By default, a bounded mailbox with capacity 64 is used to provide backpressure.
    /// For custom mailbox configuration, use [`Spawn::spawn_in_thread_with_mailbox`].
    ///
    /// # Example
    ///
    /// ```no_run
    /// use std::io::{self, Write};
    /// use std::fs::File;
    ///
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    /// use kameo::message::{Context, Message};
    ///
    /// #[derive(Actor)]
    /// struct MyActor {
    ///     file: File,
    /// }
    ///
    /// struct Flush;
    /// impl Message<Flush> for MyActor {
    ///     type Reply = io::Result<()>;
    ///
    ///     async fn handle(&mut self, _: Flush, _ctx: &mut Context<Self, Self::Reply>) -> Self::Reply {
    ///         self.file.flush() // This blocking operation is handled in its own thread
    ///     }
    /// }
    ///
    /// let actor_ref = MyActor::spawn_in_thread(
    ///     MyActor { file: File::create("output.txt").unwrap() }
    /// );
    /// actor_ref.tell(Flush).blocking_send()?;
    /// # Ok::<(), kameo::error::SendError<Flush>>(())
    /// ```
    ///
    /// This function is useful for actors that require or benefit from running blocking operations while still
    /// enabling asynchronous functionality.
    fn spawn_in_thread(args: Self::Args) -> ActorRef<Self> {
        Spawn::spawn_in_thread_with_mailbox(args, mailbox::bounded(DEFAULT_MAILBOX_CAPACITY))
    }

    /// Spawns the actor in its own dedicated thread with a specific mailbox configuration.
    ///
    /// This function allows you to explicitly specify a mailbox when spawning an actor in a dedicated thread.
    /// Use this when you need custom mailbox behavior or capacity for actors that perform blocking operations.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use std::io::{self, Write};
    /// use std::fs::File;
    ///
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    /// use kameo::mailbox;
    /// use kameo::message::{Context, Message};
    ///
    /// #[derive(Actor)]
    /// struct MyActor {
    ///     file: File,
    /// }
    ///
    /// struct Flush;
    /// impl Message<Flush> for MyActor {
    ///     type Reply = io::Result<()>;
    ///
    ///     async fn handle(&mut self, _: Flush, _ctx: &mut Context<Self, Self::Reply>) -> Self::Reply {
    ///         self.file.flush() // This blocking operation is handled in its own thread
    ///     }
    /// }
    ///
    /// let actor_ref = MyActor::spawn_in_thread_with_mailbox(
    ///     MyActor { file: File::create("output.txt").unwrap() },
    ///     mailbox::bounded(100)
    /// );
    /// actor_ref.tell(Flush).blocking_send()?;
    /// # Ok::<(), kameo::error::SendError<Flush>>(())
    /// ```
    fn spawn_in_thread_with_mailbox(
        args: Self::Args,
        (mailbox_tx, mailbox_rx): (MailboxSender<Self>, MailboxReceiver<Self>),
    ) -> ActorRef<Self> {
        let prepared_actor = PreparedActor::new((mailbox_tx, mailbox_rx));
        let actor_ref = prepared_actor.actor_ref().clone();
        prepared_actor.spawn_in_thread(args);
        actor_ref
    }

    /// Creates a new prepared actor, allowing access to its [`ActorRef`] before spawning.
    ///
    /// # Example
    ///
    /// ```
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    ///
    /// #[derive(Actor)]
    /// struct MyActor;
    ///
    /// # tokio_test::block_on(async {
    /// let other_actor = MyActor::spawn(MyActor);
    /// let prepared_actor = MyActor::prepare();
    /// prepared_actor.actor_ref().link(&other_actor).await;
    /// let actor_ref = prepared_actor.spawn(MyActor);
    /// # Ok::<(), Box<dyn std::error::Error>>(())
    /// # });
    /// ```
    fn prepare() -> PreparedActor<Self> {
        Spawn::prepare_with_mailbox(mailbox::bounded(DEFAULT_MAILBOX_CAPACITY))
    }

    /// Creates a new prepared actor with a specific mailbox configuration, allowing access to its [`ActorRef`] before spawning.
    ///
    /// This function allows you to explicitly specify a mailbox when preparing an actor.
    /// Use this when you need custom mailbox behavior or capacity.
    ///
    /// # Example
    ///
    /// ```
    /// use kameo::Actor;
    /// use kameo::actor::Spawn;
    /// use kameo::mailbox;
    ///
    ///  #[derive(Actor)]
    ///  struct MyActor;
    ///
    /// # tokio_test::block_on(async {
    /// let other_actor = MyActor::spawn(MyActor);
    /// let prepared_actor = MyActor::prepare_with_mailbox(mailbox::unbounded());
    /// prepared_actor.actor_ref().link(&other_actor).await;
    /// let actor_ref = prepared_actor.spawn(MyActor);
    /// # Ok::<(), Box<dyn std::error::Error>>(())
    /// # });
    /// ```
    fn prepare_with_mailbox(
        (mailbox_tx, mailbox_rx): (MailboxSender<Self>, MailboxReceiver<Self>),
    ) -> PreparedActor<Self> {
        PreparedActor::new((mailbox_tx, mailbox_rx))
    }

    /// Creates a supervised child actor under a supervisor.
    ///
    /// This method returns a [`SupervisedActorBuilder`] that allows you to configure
    /// restart policies and limits before spawning the child. The child will be linked
    /// to the supervisor, and the supervisor will manage its lifecycle according to the
    /// configured policies.
    ///
    /// When the child actor needs to be restarted, the provided `args` will be cloned
    /// and passed to the actor's [`on_start`](Actor::on_start) method. This requires
    /// that `Args` implements [`Clone`] + [`Sync`].
    ///
    /// **Note**: If your args type is not [`Sync`], use [`supervise_with`](Self::supervise_with)
    /// instead, which only requires [`Send`].
    ///
    /// # Parameters
    ///
    /// - `supervisor_ref`: Reference to the supervisor actor that will manage this child
    /// - `args`: Initial arguments for the child actor (must be [`Clone`] + [`Sync`])
    ///
    /// # Returns
    ///
    /// A [`SupervisedActorBuilder`] for configuring supervision behavior
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::time::Duration;
    /// use kameo::actor::{Actor, ActorRef, Spawn};
    /// use kameo::error::Infallible;
    /// use kameo::supervision::{RestartPolicy, SupervisionStrategy};
    ///
    /// struct Supervisor;
    /// impl Actor for Supervisor {
    ///     type Args = ();
    ///     type Error = Infallible;
    ///
    ///     fn supervision_strategy() -> SupervisionStrategy {
    ///         SupervisionStrategy::OneForOne
    ///     }
    ///
    ///     async fn on_start(_: Self::Args, actor_ref: ActorRef<Self>) -> Result<Self, Self::Error> {
    ///         // Spawn a supervised child
    ///         let child = Worker::supervise(&actor_ref, Worker { count: 0 })
    ///             .restart_policy(RestartPolicy::Transient)
    ///             .restart_limit(5, Duration::from_secs(10))
    ///             .spawn()
    ///             .await;
    ///
    ///         Ok(Supervisor)
    ///     }
    /// }
    ///
    /// #[derive(Clone)]
    /// struct Worker {
    ///     count: u32,
    /// }
    ///
    /// impl Actor for Worker {
    ///     type Args = Self;
    ///     type Error = Infallible;
    ///
    ///     async fn on_start(state: Self::Args, _: ActorRef<Self>) -> Result<Self, Self::Error> {
    ///         Ok(state)
    ///     }
    /// }
    /// ```
    ///
    /// [`SupervisedActorBuilder`]: crate::supervision::SupervisedActorBuilder
    fn supervise<A: Actor>(
        supervisor_ref: &ActorRef<A>,
        args: Self::Args,
    ) -> SupervisedActorBuilder<'_, A, Self>
    where
        Self::Args: Clone + Sync,
    {
        SupervisedActorBuilder::new(supervisor_ref, args)
    }

    /// Creates a supervised child actor with a factory function for generating args.
    ///
    /// This is similar to [`supervise`](Self::supervise), but instead of cloning the same
    /// args on each restart, it calls a factory function to generate new args. This is
    /// useful when:
    ///
    /// - **The actor's args don't implement [`Sync`]** (only requires [`Send`])
    /// - The actor's args don't implement [`Clone`]
    /// - You need to generate fresh state on each restart
    /// - Args need to be dynamically computed at restart time
    ///
    /// Unlike [`supervise`](Self::supervise), this method only requires `Args: Send`, making
    /// it suitable for types that cannot be safely shared across threads.
    ///
    /// # Parameters
    ///
    /// - `supervisor_ref`: Reference to the supervisor actor that will manage this child
    /// - `f`: Factory function that returns fresh args on each restart (must be [`Send`] + [`Sync`])
    ///
    /// # Returns
    ///
    /// A [`SupervisedActorBuilder`] for configuring supervision behavior
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::time::Duration;
    /// use kameo::actor::{Actor, ActorRef, Spawn};
    /// use kameo::error::Infallible;
    /// use kameo::supervision::RestartPolicy;
    ///
    /// struct Supervisor;
    /// impl Actor for Supervisor {
    ///     type Args = ();
    ///     type Error = Infallible;
    ///
    ///     async fn on_start(_: Self::Args, actor_ref: ActorRef<Self>) -> Result<Self, Self::Error> {
    ///         // Use a factory function to generate fresh state on each restart
    ///         let child = Worker::supervise_with(&actor_ref, || Worker {
    ///             // This function is called on each restart
    ///             start_time: std::time::Instant::now(),
    ///         })
    ///         .restart_policy(RestartPolicy::Transient)
    ///         .spawn()
    ///         .await;
    ///
    ///         Ok(Supervisor)
    ///     }
    /// }
    ///
    /// struct Worker {
    ///     start_time: std::time::Instant, // Not Clone
    /// }
    ///
    /// impl Actor for Worker {
    ///     type Args = Self;
    ///     type Error = Infallible;
    ///
    ///     async fn on_start(state: Self::Args, _: ActorRef<Self>) -> Result<Self, Self::Error> {
    ///         Ok(state)
    ///     }
    /// }
    /// ```
    ///
    /// [`SupervisedActorBuilder`]: crate::supervision::SupervisedActorBuilder
    fn supervise_with<A: Actor>(
        supervisor_ref: &ActorRef<A>,
        f: impl Fn() -> Self::Args + Send + Sync + 'static,
    ) -> SupervisedActorBuilder<'_, A, Self> {
        SupervisedActorBuilder::new_with(supervisor_ref, f)
    }
}

impl<A: Actor> Spawn for A {}

mod private {
    use super::Actor;

    pub trait Sealed {}
    impl<A: Actor> Sealed for A {}
}