reactive-actor
Version:
Actor model implementation with rxjs
125 lines (124 loc) • 5.59 kB
TypeScript
import { Observable, OperatorFunction } from 'rxjs';
import { AnswerConfig, Event } from '../interfaces';
import { Reducer } from '../types';
import { ActorEvent } from '../types/actor-event.type';
export declare const stop: import("../interfaces").EventCreator<unknown, ActorEvent<unknown, Event<any>>>;
/**
* Reference:
* https://www.youtube.com/watch?v=7erJ1DV_Tlo&ab_channel=jasonofthel33t
*
* Actor:
* Fundamental unit of computation
* Actor needs to embody
* - Processing
* - Storage
* - Communication
*
* "One ant is no ant" - "One human is no human" - "One actor is no actor"
* Actors live within systems
*
* Fundamental Properties:
* - Receive messages, in response of this it can"
* - Create actors
* - Send messages (to other actors and itself)
* - Designates what to do with the next message it receives
*/
export declare class Actor<TMessage extends ActorEvent = ActorEvent> {
address: string;
private readonly message$;
/**
* Stream of stop events (might be useful to know when the actor stops)
*/
readonly stop$: Observable<ActorEvent<unknown, Event<any>>>;
constructor(address: string);
/**
* Method to send messages to the actor
* @param message we want to send to the actor
*/
send(message: TMessage): void;
/**
* Subscribes to an observable of events when there is an emission will send the event to a
* recipient (actor reference) when specified and to itself when not.
* completes when stop message is send to the actor.
* @param messages an observable of messages
* @example
*
* import { Actor, createEvent } from 'reactive-actor';
*
* export const getUsers = createEvent('[Users] Get Users');
*
* export const getUsersSuccess = createEvent<GitHubUser[]>(
* '[Users] Get Users Success'
* );
*
* export const getUsersFail = createEvent<string>('[Users] Get Users Fail');
*
*
* export type UsersActorEvents = ReturnType<typeof getUsers>;
*
* export class UsersActor extends Actor<UsersActorEvents> {
* // Reference to logger actor
* private readonly logger = new Actor('logger');
*
* // Recipient is not define thus will send the resulting event to itself
* private readonly getUsers$ = this.messages$.pipe(
* ofType(getUsers),
* exhaustMap(() =>
* ajax<GitHubUser[]>(`https://api.github.com/users?per_page=5`).pipe(
* map(({ response }) => getUsersSuccess(response)),
* catchError((err) => of(getUsersFail(err)))
* )
* )
* );
*
* // Recipient is define thus will send event (getUsersFail) to specified recipient (logger)
* private readonly getUsersFail$ = this.messages$.pipe(
* ofType(getUsersFail),
* addRecipient(this.logger)
* );
*
* constructor() {
* super('users');
* this.answer(this.getUsers$, this.getUsersFail$);
* }
* }
*/
protected answer(...messages: Observable<Event & AnswerConfig>[]): void;
/**
* Actor message stream, allows to define actor behavior
* see [example](https://www.npmjs.com/package/reactive-actor)
*/
protected get messages$(): Observable<TMessage>;
}
/**
* Represents a state machine defined as a dictionary where states are keys
* and values are dictionary where events are keys and next state values
*/
export declare type EventStateMachineStructure<TState extends StateMachineState, TInput extends Event> = Partial<Record<TState, Partial<Record<TInput['type'] | string, TState>>>>;
/**
* Type synonym for state machine keys
*/
export declare type StateMachineState = string | number;
/**
* Creates an event reducer from a state machine defined as a dictionary see: ``EventStateMachineStructure``
* @param stateMachine a state machine defined as a dictionary
* @returns reducer function that process the next state based on current state and an event
*/
export declare function createStateMachineReducer<TState extends StateMachineState, TInput extends Event>(stateMachine: EventStateMachineStructure<TState, TInput>): Reducer<TState, TInput>;
/**
* Creates a function that once applied to a stream of events will reduce state and events over time
* similar to rxjs ``scan`` operator but will multicast values to subscribers
* @param reducer - a function with the form of ``(state: TState, event: TEvent) => TState``
* ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
* @param initialState state that will be reduced will the first event or state at time 0
* @returns operator function to reduce state and events over time
*/
export declare function eventReducer<TState, TMessage>(reducer: Reducer<TState, TMessage>, initialState: TState): (source$: Observable<TMessage>) => Observable<TState>;
/**
* Creates a function that once applied to a stream of events will reduce state and events over time
* similar to rxjs ``scan`` operator but will multicast values to subscribers
* @param stateMachine a state machine defined as a dictionary see: ``EventStateMachineStructure``
* @param initialState state that will be reduced will the first event or state at time 0
* @returns operator function to reduce state and events over time
*/
export declare function eventStateMachine<TState extends StateMachineState, TMessage extends Event>(stateMachine: EventStateMachineStructure<TState, TMessage>, initialState: TState): OperatorFunction<TMessage, TState>;