|
@@ -1,7 +1,166 @@
|
|
|
import { Observer, Subject, Subscribable, Unsubscribable } from "rxjs"
|
|
|
-/* --------------------------------------------
|
|
|
-Fis actor to declare its own subscribable but extended from RXJS
|
|
|
+/*Fis actor to declare its own subscribable but extended from RXJS */
|
|
|
+
|
|
|
+
|
|
|
+/* ===========Actor Message Mode Start =============
|
|
|
+
|
|
|
+ Following intefaces pertain to an Actor messaging model.
|
|
|
+ Declared as interfaces so that new member elements can be
|
|
|
+ added. This definition only list type of messages recognised
|
|
|
+ by the base Actor. Messages streamed from subscribables if
|
|
|
+ necessary need to be mapped to message type recognised by
|
|
|
+ the actor.
|
|
|
+
|
|
|
+ The concrete actor will need to add type
|
|
|
+ of schema corresponding to each of the message type in the
|
|
|
+ message model (refer to src.common.messageModel.messageSchema)
|
|
|
+
|
|
|
+ File location: src.messageModel.messageType folder.
|
|
|
+
|
|
|
+ */
|
|
|
+
|
|
|
+interface messageSchemaType {
|
|
|
+ undefined: "UNDEFINED" // when not defined
|
|
|
+ element: "ELEMENT" // fundamental unit
|
|
|
+ composite: "COMPOSITE" // has other schema
|
|
|
+}
|
|
|
+
|
|
|
+export interface MessageSchemaService extends CRUD {
|
|
|
+ /* collection of method signatures*/
|
|
|
+}
|
|
|
+
|
|
|
+export interface MessageSchemaDataModel {
|
|
|
+ schemaId: string // identifier
|
|
|
+ schemaName: string // unique legible name
|
|
|
+ schemaDef: string // jason description of schema
|
|
|
+ schemaType: messageSchemaType // one of selection
|
|
|
+ isConcrete: boolean // whether is consumable message
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+export interface MessageSchema {
|
|
|
+/* Descsription steriotype for all Fis messages.
|
|
|
+ Has reference to message schema described as interfaces.
|
|
|
+ MessageSchema is a network structure (not a tree hierarchy) where
|
|
|
+ a child schema may have multiple parent schema
|
|
|
+ Definition begins at the lowest denomiator
|
|
|
+ schema, or lowest node.
|
|
|
+ On handling version of message schema, refer to version model
|
|
|
*/
|
|
|
+ messageSchemaDataModel: MessageSchemaDataModel
|
|
|
+ messageSchemaService: MessageSchemaService
|
|
|
+}
|
|
|
+
|
|
|
+export interface MessageSchemaCompositeAssociation {
|
|
|
+/* Associated nodes of a composite schema.
|
|
|
+ Note association is one directional */
|
|
|
+ compositeMessageSchema: MessageSchema
|
|
|
+ compositeEntries: Array <MessageSchema>[]
|
|
|
+ /* associated to schema */
|
|
|
+}
|
|
|
+
|
|
|
+export class MessageSchemaImpl implements MessageSchema {
|
|
|
+
|
|
|
+ messageSchemaDataModel: MessageSchemaDataModel
|
|
|
+
|
|
|
+ constructor (messageSchemaDataModel: MessageSchemaDataModel) {
|
|
|
+ this.messageSchemaDataModel = messageSchemaDataModel
|
|
|
+ }
|
|
|
+ /* validation:
|
|
|
+ - if schemaId is not provided by creator, then self generate
|
|
|
+ - schemaDef should be a valid schema (call api to check)
|
|
|
+ - value changed should emit value changed event to be
|
|
|
+ - handled by for example version logging
|
|
|
+ */
|
|
|
+}
|
|
|
+
|
|
|
+export class MessageSchemaElement extends MessageSchemaImpl {
|
|
|
+/* fundamental unit of a schema by which composite schema is constructed */
|
|
|
+
|
|
|
+ messageSchemaElementDataModel: MessageSchemaDataModel
|
|
|
+
|
|
|
+ constructor (messageSchemaElementDataModel: MessageSchemaDataModel) {
|
|
|
+ super (messageSchemaElementDataModel)
|
|
|
+ this.messageSchemaElementDataModel = messageSchemaElementDataModel
|
|
|
+ }
|
|
|
+
|
|
|
+ /* validation:
|
|
|
+ - schema definition should not contain other schema
|
|
|
+ -
|
|
|
+ */
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/* this section of the code to be saved in file
|
|
|
+ src/common/services/ */
|
|
|
+
|
|
|
+export interface CRUD {
|
|
|
+ /* standard method signature for common entity behaviour*/
|
|
|
+ create<T>(dataModel: T): null
|
|
|
+ read<T>(): T
|
|
|
+ update<T>(dataModel: T): null
|
|
|
+ delete<T>(): null
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+export interface ActorCommands {
|
|
|
+/* base actor commands*/
|
|
|
+ Subscribe: "SUBSCRIBE", // subsribe to incoming bus
|
|
|
+ UnSubscribe: "UNSUBSCRIBE", // unsubscribe a subscribable
|
|
|
+ Initialise: "INITIALISE", // initialise to ready actor
|
|
|
+ Reset: "RESET", // reset actor to initial state
|
|
|
+ ShutDown: "SHUTDOWN" // shutdown actor
|
|
|
+}
|
|
|
+export interface ActorCommandStatus {
|
|
|
+ CommandReceived: "COMMANDRECEIVED", // received and que
|
|
|
+ CommandCancelled: "COMMANDCANCELLED", // cancelled from que
|
|
|
+ CommandExeStarted: "COMMANDEXESTARTS",
|
|
|
+ CommandExeEnded: "COMMANDEXEENDED",
|
|
|
+ CommandCompleted: "COMMANDCOMPLETED"
|
|
|
+}
|
|
|
+export interface ActorCommandError {
|
|
|
+/* recoverable errors */
|
|
|
+ UnRecognisedCommand: "UNRECOGNISEDCOMMAND"
|
|
|
+ CommandExecutionError: "COMMANDEXECUTIONERROR"
|
|
|
+}
|
|
|
+export interface CommandNotification {
|
|
|
+ ActorCommandStatus: ActorCommandStatus
|
|
|
+ ActorCommandError: ActorCommandError
|
|
|
+}
|
|
|
+
|
|
|
+export interface ActorQuery {
|
|
|
+ GetActorIdentifier: "GETACTORIDENTY",
|
|
|
+ GetSubscribables: "GETSUBSCRIBABLES", // return list of subscribable identities
|
|
|
+ GetSubscribabers: "GETSUBSCRIBERS", // return list of observer identities
|
|
|
+}
|
|
|
+export interface ActorQueriesResponse {
|
|
|
+ QueryData: "GETACTORIDENTY",
|
|
|
+ QuerySummary: "GETSUBSCRIBABLES", // return list of subscribable identities
|
|
|
+ QueryStatus: "GETSUBSCRIBERS", // return list of observer identities
|
|
|
+}
|
|
|
+export interface ActorIrrecoverableError {
|
|
|
+ InternalError: "INTERNAL ERROR", // withinn actor
|
|
|
+ EnvironmentError: "ENVIRONMENTERROR", // outside actor
|
|
|
+ UnknownError: "UNKNOWNERROR" } // unable to identify
|
|
|
+export interface ActorNotification {
|
|
|
+ ActorLifeCycle: ActorFiniteState,
|
|
|
+ ActorIrrecoverableError: ActorIrrecoverableError
|
|
|
+}
|
|
|
+export interface ActorFiniteState {
|
|
|
+ Initialising: "INITIALISING",
|
|
|
+ Ready: "READY",
|
|
|
+ Executing: "EXECUTING",
|
|
|
+ Paused: "PAUSED",
|
|
|
+ ShuttingDown: "SHUTDOWN",
|
|
|
+ Ended: "ENDED"
|
|
|
+}
|
|
|
+//export type actorMessageModel = (commands: ActorCommands, queries: ActorQueries)
|
|
|
+
|
|
|
+/* ===========Actor Message Model End ============= */
|
|
|
+
|
|
|
+
|
|
|
interface ActorService {
|
|
|
/* Stateful actor service to be instantiated by concrete class.
|
|
|
To add in behaviour and model state repository */
|
|
@@ -11,6 +170,10 @@ interface ActorContext<T> {
|
|
|
/* Environment within which actor operates. Provided by creator in
|
|
|
constructor */
|
|
|
defaultSubscribers: FisActor<T>[]
|
|
|
+ /* instances of observer actors expected to subscribe upon creation of this actor */
|
|
|
+ defaultSubscribables: FisActor<T>[]
|
|
|
+ /* instances of actors to auto subscribe to upon creation.
|
|
|
+ This would include the Supervisor */
|
|
|
}
|
|
|
|
|
|
interface ActorServiceContext {
|
|
@@ -22,18 +185,47 @@ interface FisActor<T> extends Subscribable<T> {
|
|
|
subscribe(observer: Partial<Observer<T>>): Unsubscribable
|
|
|
}
|
|
|
|
|
|
-export abstract class FisActorBaseImpl<T> implements FisActor<T> {
|
|
|
+
|
|
|
+/* ============ Actor model base ================== */
|
|
|
+
|
|
|
+
|
|
|
+export class FisActorImpl<T> implements FisActor<T> {
|
|
|
+
|
|
|
+ /* A Fis actor is stateful object which implements Subscribable
|
|
|
+ interface. It can be anything including:
|
|
|
+ business domain object
|
|
|
+ UI component
|
|
|
+ message forwarder
|
|
|
+ actor directory receptionist
|
|
|
+ actor container
|
|
|
+ remote transmission service
|
|
|
+ mircroservice
|
|
|
+ client proxy
|
|
|
+ domain proxy
|
|
|
+ backoffice App Manager
|
|
|
+
|
|
|
+ Behavior of an actor is solely dependent on the actor service
|
|
|
+ passed from its creator actor
|
|
|
+
|
|
|
+ Folder location: src.common.actor
|
|
|
+*/
|
|
|
+
|
|
|
protected actorId!: String
|
|
|
/* autogenerate a GUID value upon creation */
|
|
|
|
|
|
- protected actorName: String | null = null
|
|
|
- protected incomingBus!: Subscribable<T>
|
|
|
- protected outgoingBus!: Subscribable<T>
|
|
|
- protected actorService!: ActorService
|
|
|
- protected actorContext!: ActorContext<T>
|
|
|
+ protected actorName: String = "No Name" //might be reassigned during run time
|
|
|
+ protected incomingBus: Subscribable<T> = new Subject
|
|
|
+ protected outgoingBus: Subscribable<T> = new Subject
|
|
|
+ protected actorService!: ActorService // service provided by creator
|
|
|
+ protected actorContext!: ActorContext<T> // context provided by creator
|
|
|
protected actorServiceContext!: ActorServiceContext
|
|
|
-
|
|
|
+ protected supervisorActor!: FisActor<T>
|
|
|
+ /* Supervisor assigned by creator. A creator us usually but not aways the Supervisor.
|
|
|
+ An Actor will always has a Supervisor Actor unless it is a Root Actor.
|
|
|
+ Note that an Aggregate Root Actor (for CQRS context) is not the same as Root Actor
|
|
|
+ */
|
|
|
|
|
|
+
|
|
|
constructor(actorContext: ActorContext<T>) {
|
|
|
// logic here
|
|
|
}
|
|
@@ -45,6 +237,7 @@ export abstract class FisActorBaseImpl<T> implements FisActor<T> {
|
|
|
throw new Error("Method to be defined....")
|
|
|
}
|
|
|
|
|
|
+
|
|
|
}
|
|
|
|
|
|
interface Actor<T> extends Subscribable<T> {
|