Skip to content

Commit

Permalink
Doc (#262)
Browse files Browse the repository at this point in the history
* doc(): updated

* doc(./docs/class/incomer): enhanced eventCallback doc
  • Loading branch information
Rossb0b authored Jul 31, 2024
1 parent 113f619 commit 459cec0
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 42 deletions.
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,19 @@ if (isDeleteOperation(event.operation)) {
| variable | description | default |
| --- | --- | --- |
| `MYUNISOFT_INCOMER_INIT_TIMEOUT` | Incomer initialisation timeout | `3_500` |
| `MYUNISOFT_EVENTS_INIT_EXTERNAL` | Weither Incomer should initialise an external Dispatcher | `false` |
| `MYUNISOFT_EVENTS_LOGGER_MODE` | Set log level for the default logger | `info` |
| `MYUNISOFT_INCOMER_MAX_PING_INTERVAL` | Maximum ping interval | `60_000` |
| `MYUNISOFT_INCOMER_PUBLISH_INTERVAL` | Publish interval | `60_000` |
| `MYUNISOFT_INCOMER_IS_DISPATCHER` | Weither Incomer is a Dispatcher | `false` |
| <b>Dispatcher</b> |
| `MYUNISOFT_DISPATCHER_IDLE_TIME` | Interval threshold when Dispatcher become idle | `600_000` |
| `MYUNISOFT_DISPATCHER_CHECK_LAST_ACTIVITY_INTERVAL` | Dispatcher checking last activity interval | `120_000` |
| `MYUNISOFT_DISPATCHER_BACKUP_TRANSACTION_STORE_NAME` | Default name for backup transaction store | `backup` |
| `MYUNISOFT_DISPATCHER_INIT_TIMEOUT` | Dispatcher initialisation timeout | `3_500` |
| `MYUNISOFT_DISPATCHER_PING_INTERVAL` | Dispatcher ping interval | `3_500` |
| <b>Incomer</b> |
| `MYUNISOFT_INCOMER_INIT_TIMEOUT` | Incomer initialisation timeout | `3_500` |
| `MYUNISOFT_EVENTS_INIT_EXTERNAL` | Whenever Incomer should initialize an external Dispatcher | `false` |
| `MYUNISOFT_INCOMER_MAX_PING_INTERVAL` | Maximum ping interval | `60_000` |
| `MYUNISOFT_INCOMER_PUBLISH_INTERVAL` | Publish interval | `60_000` |
| `MYUNISOFT_INCOMER_IS_DISPATCHER` | Weither Incomer is a Dispatcher | `false` |

### API

Expand All @@ -161,7 +163,7 @@ if (isDeleteOperation(event.operation)) {

#### validate< T extends keyof Events >(options: EventOptions<T>): void

> Throw an error if a given event is not internaly known.
> Throw an error if a given event is not internally known.
---

Expand Down
38 changes: 32 additions & 6 deletions docs/class/dispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type DispatcherOptions<T extends GenericEvent = GenericEvent> = {
<br/>

> Default logger is a pino logger. <br/>
> ⚠️ You can inject your own but you must ensure that the provided logger has those methods `info` | `error` | `warn`.
> ⚠️ You can inject your own but you must ensure that the provided logger has those methods `info` | `error` | `warn` | `debug`.
</details>

Expand All @@ -64,12 +64,32 @@ type DispatcherOptions<T extends GenericEvent = GenericEvent> = {
> Callback function use to formate logs related to custom events casting.
```ts
type StandardLogOpts<T extends GenericEvent = GenericEvent> = T & {
redisMetadata: {
transactionId: string;
origin?: string;
to?: string;
eventTransactionId?: string;
}
};
```

> Default Callback function used.
```ts
function logValueFallback(value: string): string {
return value ?? "none";
}

function standardLog<T extends GenericEvent = EventOptions<keyof Events>>
(event: T & { redisMetadata: { transactionId: string } }) {
const logs = `foo: ${event.foo}`;
(data: StandardLogOpts<T>) {
const logs = Array.from(mapped<T>(event)).join("|");

// eslint-disable-next-line max-len
const eventMeta = `name:${logValueFallback(event.name)}|ope:${logValueFallback(event.operation)}|from:${logValueFallback(event.redisMetadata.origin)}|to:${logValueFallback(event.redisMetadata.to)}`;

function log(message: string) {
return `(${logs}) ${message}`;
return `(${logs})(${eventMeta}) ${message}`;
}

return log;
Expand All @@ -88,10 +108,14 @@ function standardLog<T extends GenericEvent = EventOptions<keyof Events>>
> Map of Ajv validation functions related to events.
```ts
const eventsValidationFn: MappedEventsValidationFn = new Map<string, CustomEventsValidationFunctions>();
type NestedValidationFunctions = Map<string, ValidateFunction<Record<string, any>>>;

type eventsValidationFn<T extends GenericEvent> = Map<string, ValidateFunction<T> | NestedValidationFunctions>;

export const eventsValidationFn: MappedEventsValidationFn = new Map<string, NestedValidationFunctions>();

for (const [name, validationSchemas] of Object.entries(eventsValidationSchemas)) {
const operationsValidationFunctions: Map<string, ValidateFunction<OperationFunctions>> = new Map();
const operationsValidationFunctions: Map<string, ValidateFunction<Record<string, any>>> = new Map();

for (const [operation, validationSchema] of Object.entries(validationSchemas)) {
operationsValidationFunctions.set(operation, ajv.compile(validationSchema));
Expand All @@ -106,6 +130,8 @@ for (const [name, validationSchemas] of Object.entries(eventsValidationSchemas))
> Callback validation function used to validate events according to the given eventsValidationFn.
```ts
type customValidationCbFn<T extends GenericEvent> = (event: T) => void;

function validate<T extends keyof Events = keyof Events>(options: EventOptions<T>) {
const { name, operation, data, scope, metadata } = options;

Expand Down
112 changes: 82 additions & 30 deletions docs/class/incomer.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,27 @@ const incomer = new Incomer({
name: "foo",
eventsCast: [...Object.keys(AVAILABLE_EVENTS)],
eventsSubscribe: [...Object.values(AVAILABLE_EVENTS)],
eventCallback: (event) => {
console.log(event);

return OK({ status: "RESOLVED" });
eventCallback: async(event) => {
try {
// Do some async work
}
catch (error) {
if (error.reason === "ANY_RETRY_ERROR") {
return OK({
status: "UNRESOLVED",
reason: error.stack,
retryStrategy: {
maxIteration: 1
}
});
}

return Err(error.stack);
}

return OK({
status: "RESOLVED"
});
}
});

Expand All @@ -45,7 +62,11 @@ await incomer.close();
```ts
type Prefix = "test" | "development" | "staging" | "production";

type GenericEvent = Record<string, any> & { data: Record<string, any> };
type GenericEvent = {
name: string;
data: Record<string, any>;
[key: string]: any;
};

type EventCast<T extends string | keyof Events = string> = T;

Expand All @@ -58,26 +79,48 @@ type EventSubscribe<T extends string | keyof Events = string> = {
type CallBackEventMessage<
T extends GenericEvent = GenericEvent
> = T & {
name: string;
eventTransactionId: string;
};

type EventMessage<
T extends GenericEvent = GenericEvent
> = T & {
name: string;
redisMetadata: IncomerTransactionMetadata;
};
export type Resolved = "RESOLVED";
export type Unresolved = "UNRESOLVED";

type EventCallbackResponse<T extends Resolved | Unresolved = Resolved | Unresolved> = Result<
T extends Resolved ? {
status: T;
} : {
status: T;
retryStrategy?: {
maxIteration: number;
};
reason: string;
}, string>;

type NestedValidationFunctions = Map<string, ValidateFunction<Record<string, any>>>;

type customValidationCbFn<T extends GenericEvent> = (event: T) => void;
type eventsValidationFn<T extends GenericEvent> = Map<string, ValidateFunction<T> | NestedValidationFunctions>;

type IncomerOptions<T extends GenericEvent = GenericEvent> = {
/* Service name */
name: string;
prefix?: Prefix;
logger?: Partial<Logger> & Pick<Logger, "info" | "warn">;
standardLog?: StandardLog<T>;
eventsCast: EventCast[];
eventsSubscribe: EventSubscribe[];
eventsValidation?: {
eventsValidationFn?: eventsValidationFn<T>;
customValidationCbFn?: customValidationCbFn<T>;
};
eventCallback: (message: CallBackEventMessage<T>) => Promise<EventCallbackResponse>;
prefix?: Prefix;
abortPublishTime?: number;
dispatcherInactivityOptions?: {
/* max interval between received ping before considering dispatcher off */
maxPingInterval?: number;
/* max interval between a new event (based on ping interval) */
publishInterval?: number;
};
isDispatcherInstance?: boolean;
externalsInitialized?: boolean;
};
```
Expand All @@ -90,7 +133,7 @@ type IncomerOptions<T extends GenericEvent = GenericEvent> = {
<br/>

> Default logger is a pino logger. <br/>
> ⚠️ You can inject your own but you must ensure that the provided logger has those methods `info` | `error` | `warn`.
> ⚠️ You can inject your own but you must ensure that the provided logger has those methods `info` | `error` | `warn` | `debug`.
</details>

Expand All @@ -103,12 +146,32 @@ type IncomerOptions<T extends GenericEvent = GenericEvent> = {
> Callback function use to formate logs related to custom events casting.
```ts
type StandardLogOpts<T extends GenericEvent = GenericEvent> = T & {
redisMetadata: {
transactionId: string;
origin?: string;
to?: string;
eventTransactionId?: string;
}
};
```

> Default Callback function used.
```ts
function logValueFallback(value: string): string {
return value ?? "none";
}

function standardLog<T extends GenericEvent = EventOptions<keyof Events>>
(event: T & { redisMetadata: { transactionId: string } }) {
const logs = `foo: ${event.foo}`;
(data: StandardLogOpts<T>) {
const logs = Array.from(mapped<T>(event)).join("|");

// eslint-disable-next-line max-len
const eventMeta = `name:${logValueFallback(event.name)}|ope:${logValueFallback(event.operation)}|from:${logValueFallback(event.redisMetadata.origin)}|to:${logValueFallback(event.redisMetadata.to)}`;

function log(message: string) {
return `(${logs}) ${message}`;
return `(${logs})(${eventMeta}) ${message}`;
}

return log;
Expand All @@ -119,17 +182,6 @@ function standardLog<T extends GenericEvent = EventOptions<keyof Events>>

---

<details>
<summary><b>abortPublishTime</b></summary>
<br/>

> Interval of time during which the `incomer` instance is going to wait to for a response from the `dispatcher` next to the registration demand or any event publishing. <br/>
> If there is no recent activity from the `dispatcher`, those events are not publish and saved in Redis awaiting for the next iteration.
</details>

---

<details>
<summary><b>externalsInitialized</b></summary>
<br/>
Expand All @@ -140,7 +192,7 @@ function standardLog<T extends GenericEvent = EventOptions<keyof Events>>

## API

### publish< K extends GenericEvent | null = null >(event: K extends null ? Omit< EventMessage< T >, "redisMetadata" >): Promise<void>
### publish(event: T): Promise<void>

> Publish the given event on Redis pubsub. <br/>
> If there is no dispatcher alive, the event isn't publish but saved in Redis awaiting for an incoming publish.

0 comments on commit 459cec0

Please sign in to comment.