Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoSign in
Socket

@actor-system/core

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@actor-system/core - npm Package Compare versions

Comparing version
0.1.0
to
0.1.1
+3
-1
dist/actor/actor-system.internal.d.ts

@@ -68,3 +68,5 @@ import { Path } from '../__bundle__/shared/dist/path.internal.js';

*/
_lookupMailboxConfig(actorPath: Path.Actor): MailboxConfig;
_lookupMailboxConfig(actorPath: Path.Actor): {
scheduler: PriorityScheduler;
} | MailboxConfig<unknown>;
/** @internal */

@@ -71,0 +73,0 @@ _stopActor(actor: Actor): Promise<void>;

@@ -11,4 +11,4 @@ import { ActorMessagePort, ActorPostPort, MailboxConfig, MailboxState } from './types.js';

#private;
static create<T>(config: MailboxConfig): Mailbox<T>;
constructor(config: MailboxConfig);
static create<T>(config: MailboxConfig<T>): Mailbox<T>;
constructor(config: MailboxConfig<T>);
set onmessage(handler: Bivariant<(event: T | SystemMessage) => void> | null);

@@ -20,2 +20,19 @@ /**

get onmessage(): Bivariant<(event: T | SystemMessage) => void> | null;
/**
* Posts a message to the mailbox. The message can be either a user-defined event of type `T`
* or a system message. The method handles different mailbox states:
* - If the mailbox is shut down, the message is ignored.
* - If the mailbox is shutting down, only system messages are accepted.
* - If the mailbox is disconnected, the message is buffered.
* - Otherwise, the message is enqueued and the mailbox is drained.
*
* @param event The message to post, either of type `T` or a `SystemMessage`.
* @returns A promise that resolves when the message has been processed.
*
* @remarks
* **Performance:**
* - The time complexity of posting a message is typically **O(1)** for both buffering and enqueuing operations,
* assuming the underlying queue and buffer implementations are constant time.
* - The overall performance may depend on the implementation of `#drain()`, which is not detailed here.
*/
postMessage(event: T | SystemMessage): Promise<void>;

@@ -22,0 +39,0 @@ get state(): MailboxState;

@@ -11,4 +11,4 @@ import { ActorMessagePort, ActorPostPort, MailboxConfig, MailboxState } from './types.internal.js';

#private;
static create<T>(config: MailboxConfig): Mailbox<T>;
constructor(config: MailboxConfig);
static create<T>(config: MailboxConfig<T>): Mailbox<T>;
constructor(config: MailboxConfig<T>);
set onmessage(handler: Bivariant<(event: T | SystemMessage) => void> | null);

@@ -20,2 +20,19 @@ /**

get onmessage(): Bivariant<(event: T | SystemMessage) => void> | null;
/**
* Posts a message to the mailbox. The message can be either a user-defined event of type `T`
* or a system message. The method handles different mailbox states:
* - If the mailbox is shut down, the message is ignored.
* - If the mailbox is shutting down, only system messages are accepted.
* - If the mailbox is disconnected, the message is buffered.
* - Otherwise, the message is enqueued and the mailbox is drained.
*
* @param event The message to post, either of type `T` or a `SystemMessage`.
* @returns A promise that resolves when the message has been processed.
*
* @remarks
* **Performance:**
* - The time complexity of posting a message is typically **O(1)** for both buffering and enqueuing operations,
* assuming the underlying queue and buffer implementations are constant time.
* - The overall performance may depend on the implementation of `#drain()`, which is not detailed here.
*/
postMessage(event: T | SystemMessage): Promise<void>;

@@ -22,0 +39,0 @@ get state(): MailboxState;

@@ -12,2 +12,3 @@ import { waitForScheduler } from '../schedulers/waitForScheduler.js';

#scheduler;
#messageComparator;
#systemQueue = [];

@@ -25,2 +26,3 @@ #queue = [];

this.#scheduler = config.scheduler;
this.#messageComparator = config.messageComparator;
}

@@ -31,3 +33,5 @@ set onmessage(handler) {

this.#onmessage = null;
this.#state = this.#state === "shutdown" ? "shutdown" : "disconnected";
if (this.#state !== "shutdown") {
this.#state = "disconnected";
}
return;

@@ -39,3 +43,7 @@ }

this.#systemQueue.push(...this.#pendingSystemMessages.splice(0));
this.#queue.push(...this.#pendingMessages.splice(0));
// Insert pending messages in priority order
const pendingMessages = this.#pendingMessages.splice(0);
for (const message of pendingMessages) {
this.#insertSorted(this.#queue, message);
}
// Start processing if there are messages

@@ -51,31 +59,57 @@ this.#drain();

}
/**
* Posts a message to the mailbox. The message can be either a user-defined event of type `T`
* or a system message. The method handles different mailbox states:
* - If the mailbox is shut down, the message is ignored.
* - If the mailbox is shutting down, only system messages are accepted.
* - If the mailbox is disconnected, the message is buffered.
* - Otherwise, the message is enqueued and the mailbox is drained.
*
* @param event The message to post, either of type `T` or a `SystemMessage`.
* @returns A promise that resolves when the message has been processed.
*
* @remarks
* **Performance:**
* - The time complexity of posting a message is typically **O(1)** for both buffering and enqueuing operations,
* assuming the underlying queue and buffer implementations are constant time.
* - The overall performance may depend on the implementation of `#drain()`, which is not detailed here.
*/
async postMessage(event) {
if (this.#state === "shutdown")
return;
const isSysMsg = isSystemMessage(event);
// During shutting-down, only accept system messages
if (this.#state === "shutting-down" && !isSysMsg)
if (this.#state === "shutting-down" &&
!isSystemMessage(event)) {
return;
const promiseWithResolvers = Promise.withResolvers();
}
let queuedItem;
if (this.#state === "disconnected") {
// Buffer messages until connected
if (isSysMsg) {
this.#pendingSystemMessages.push({ event, ...promiseWithResolvers });
}
else {
this.#pendingMessages.push({ event, ...promiseWithResolvers });
}
queuedItem = this.#bufferPendingMessage(event);
}
else {
// Add to processing queues
if (isSysMsg) {
this.#systemQueue.push({ event, ...promiseWithResolvers });
}
else {
this.#queue.push({ event, ...promiseWithResolvers });
}
queuedItem = this.#enqueueMessage(event);
this.#drain();
}
return promiseWithResolvers.promise;
return queuedItem.promise;
}
#bufferPendingMessage(event) {
if (isSystemMessage(event)) {
const item = { event, ...Promise.withResolvers() };
this.#pendingSystemMessages.push(item);
return item;
}
const item = { event, ...Promise.withResolvers() };
this.#insertSorted(this.#pendingMessages, item);
return item;
}
#enqueueMessage(event) {
if (isSystemMessage(event)) {
const item = { event, ...Promise.withResolvers() };
this.#systemQueue.push(item);
return item;
}
const item = { event, ...Promise.withResolvers() };
this.#insertSorted(this.#queue, item);
return item;
}
get state() {

@@ -108,2 +142,28 @@ return this.#state;

}
/**
* Inserts a `QueueItem` into the given queue array, maintaining sorted order according to the
* configured message comparator. If no comparator is set, the item is appended to the end (FIFO).
*
* This method performs a linear search to find the correct insertion index, resulting in a time
* complexity of O(n), where n is the length of the queue.
*
* @param queue - The array of `QueueItem<T>` objects to insert into.
* @param item - The `QueueItem<T>` to be inserted.
*/
#insertSorted(queue, item) {
if (!this.#messageComparator) {
// No comparator, just append (FIFO)
queue.push(item);
return;
}
// Find insertion point to maintain priority order
let insertIndex = queue.length;
for (let i = 0; i < queue.length; i++) {
if (this.#messageComparator(item.event, queue[i].event) < 0) {
insertIndex = i;
break;
}
}
queue.splice(insertIndex, 0, item);
}
#drain() {

@@ -119,2 +179,19 @@ const isEmpty = this.#queue.length === 0 && this.#systemQueue.length === 0;

}
/**
* Drains the mailbox queues by processing each queued message asynchronously.
*
* This method iterates over both the system and regular message queues, invoking the
* `onmessage` handler for each item until the queues are empty or the mailbox enters
* a shutdown state. It ensures that messages are processed in order and respects
* the mailbox's lifecycle states.
*
* Performance:
* - Time Complexity: O(n), where n is the total number of messages in both queues.
* Each message is processed once per invocation.
* - Space Complexity: O(1), as no additional space is allocated proportional to the
* number of messages; only references to the current item and ongoing process are maintained.
*
* @returns {Promise<void>} Resolves when all messages have been processed or the mailbox is shut down.
* @private
*/
async #unsafeDrain() {

@@ -121,0 +198,0 @@ const { promise: ongoingProcess, resolve } = Promise.withResolvers();

import { Scheduler } from '../schedulers/types.js';
import { Bivariant } from '../__bundle__/shared/dist/types.js';
interface MailboxConfig {
interface MailboxConfig<T = unknown> {
/**

@@ -9,2 +10,12 @@ * Scheduler to use for processing messages.

scheduler: Scheduler;
/**
* Optional comparator for prioritizing user messages.
* System messages always take precedence over user messages.
* Within user messages, this comparator determines ordering.
*
* @param a - First message to compare
* @param b - Second message to compare
* @returns - Negative if a has higher priority, positive if b has higher priority, 0 if equal
*/
messageComparator?: Bivariant<(a: T, b: T) => number>;
}

@@ -11,0 +22,0 @@ type ActorMessageListener<T> = (message: T) => void;

import { Scheduler } from '../schedulers/types.internal.js';
import { Bivariant } from '../__bundle__/shared/dist/types.internal.js';
interface MailboxConfig {
interface MailboxConfig<T = unknown> {
/**

@@ -9,2 +10,12 @@ * Scheduler to use for processing messages.

scheduler: Scheduler;
/**
* Optional comparator for prioritizing user messages.
* System messages always take precedence over user messages.
* Within user messages, this comparator determines ordering.
*
* @param a - First message to compare
* @param b - Second message to compare
* @returns - Negative if a has higher priority, positive if b has higher priority, 0 if equal
*/
messageComparator?: Bivariant<(a: T, b: T) => number>;
}

@@ -11,0 +22,0 @@ type ActorMessageListener<T> = (message: T) => void;

{
"name": "@actor-system/core",
"version": "0.1.0",
"version": "0.1.1",
"type": "module",

@@ -12,3 +12,9 @@ "scripts": {

"build:tsc:trimmed": "tsc -b src/tsconfig.lib.trimmed.json",
"build:rollup": "rollup -c node:config/rollup-config"
"build:rollup": "rollup -c node:config/rollup-config",
"test": "NODE_OPTIONS=\"--expose-gc\" vitest run",
"test:browser": "vitest run --browser.enabled",
"test:browser:watch": "vitest --browser.enabled",
"test:browser:coverage": "vitest run --coverage --browser.enabled",
"test:extensive": "npm run test && npm run test -- --mode sync && npm run test:browser && npm run test:browser -- --mode sync",
"test:coverage": "vitest run --coverage"
},

@@ -15,0 +21,0 @@ "module": "./dist/index.js",