package camfish import "iter" import "context" var env environment // Run runs the daemon given the slice of actors, and shuts down the program // when all running actors have stopped. Error and log messages will be printed. // The correct way to use this function is to have it be the only thing in main: // // func main() { // camfish.Run("name", "what it does", new(SomeActor), new(AnotherActor)) // } // // Run operates in several phases. In each phase that involves actors, the // actors are operated on in the order they are specified in the variadic actors // argument. This as well as the order of the phases is considered part of the // API and are stable for versions above v1.0.0, but some exact details such as // timing are not and may change in the future. The phases are as follows: // // 10. Flag parsing: Actors which implement [FlagAdder] are given an object // which will allow them to add command line flags. Actors are given the // object one after the other in the order that they are specified in the // vararg list for Run. The flags are then parsed, giving values to the // actors that requested them. // // 20. Log switching: The environment begins redirecting all logging output to // a file if specified in the flags. After Run exits, logging will be // redirected back to [os.Stderr]. // // 30. Configuration parsing: The configuration file is parsed. If a specific // file was not specified by a flag, it is loaded from // /etc//.conf // // 40. Configuration processing: Actors which implement [ConfigProcessor] are // given a MutableConfig to read and modify. Actors are given the config // one after the other in the order that they are specified in the vararg // list for Run. Actors can use flag values they have received to override // config values, apply macros, etc. // // 50. Configuration application: Actors which implement [Configurable] are // given a [Config] to read. The order is not guaranteed. // // 60. Initialization: Actors which implement [Initializable] are initialized // in parallel. During this time, actors may do things like establish // network connections, start up servers, initialize data structures, etc. // Actors may establish references to each-other during this time, but // they must not interact yet. The amount of time actors have to do this // is configurable, but by default it is 8 minutes. The vast majority of // actors should initialize in under 100 milliseconds. // // 70. Running: Actors which implement [Runnable] or [RunShutdownable] are // run, each in their own goroutine. The environment is able to restart // actors which have failed, which entails resetting the actor if it // implements [Resettable], and running the actor again within the same // goroutine. If an actor does not run for a meaningful amount of time // after resetting/initialization before failing, it is considered erratic // and further attempts to restart it will be spaced by a limited, // constantly increasing time interval. The timing is configurable, but by // default the threshold for a meaningful amount of runtime is 16 seconds, // the initial delay interval is 8 seconds, the interval increase per // attempt is 8 seconds, and the maximum interval is one hour. // Additionally, programs which implement [Trimmable] will be trimmed // regularly whenever they are running. The trimming interval is also // configurable, but by default it is once every minute. When an actor // which implements [Resettable] is reset, it is given a configurable // timeout, which is 8 minutes by default. // // 80. Shutdown: This can be triggered by all actors being removed from the // environment, a catastrophic error, [Done] being called, or the program // recieving SIGINT. If necessary, the environment shuts down all running // actors and waits for them to stop. If they do not all stop in time, an // error message is printed and the program will exit with a non-zero code. // Otherwise, it will exit with a code of 0. The amount of time actors // have to shut down is configurable, but by default it is 8 minutes. func Run(name, description string, actors ...Actor) { env.Run(name, description, actors...) } // Done sends a shutdown signal to the environment with the given "cause" error. // This will be logged as the reason for the shutdown. func Done(cause error) { env.Done(cause) } // Add adds an actor to the environment, starting it if necessary. If the // environment is not running, it does nothing. Note that this function will // block the current goroutine while the actors are initializing. func Add(ctx context.Context, actors ...Actor) error { return env.Add(ctx, actors...) } // Del removes an actor from the environment, stopping it if necessary. If the // environment is not running, it does nothing. Note that this function will // block the current goroutine while the actors are shutting down. func Del(ctx context.Context, actors ...Actor) error { return env.Del(ctx , actors...) } // Find finds an actor in the environment with the given type name. If no actor // is found or the environment is not running, it returns nil. func Find(typ string) Actor { return env.Find(typ) } // FindAll returns an iterator over all actors in the environment with the given // type name. If the environment is not running, it returns an empty iterator. func FindAll(typ string) iter.Seq[Actor] { return env.FindAll(typ) } // All returns an iterator over all actors in the environment. If the // environment is not running, it returns an empty iterator. func All() iter.Seq[Actor] { return env.All() } // Verb returns true if verbose output is permitted. Actors should log less // information when this is false. func Verb() bool { return env.Verb() } // tell me how tf its snowiung outside if its 33° f