Skip to content
This repository was archived by the owner on Oct 22, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions packages/actor-core/fixtures/driver-test-suite/action-timeout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { actor, setup } from "actor-core";

// Short timeout actor
const shortTimeoutActor = actor({
state: { value: 0 },
options: {
action: {
timeout: 50, // 50ms timeout
},
},
actions: {
quickAction: async (c) => {
return "quick response";
},
slowAction: async (c) => {
// This action should timeout
await new Promise((resolve) => setTimeout(resolve, 100));
return "slow response";
},
},
});

// Long timeout actor
const longTimeoutActor = actor({
state: { value: 0 },
options: {
action: {
timeout: 200, // 200ms timeout
},
},
actions: {
delayedAction: async (c) => {
// This action should complete within timeout
await new Promise((resolve) => setTimeout(resolve, 100));
return "delayed response";
},
},
});

// Default timeout actor
const defaultTimeoutActor = actor({
state: { value: 0 },
actions: {
normalAction: async (c) => {
await new Promise((resolve) => setTimeout(resolve, 50));
return "normal response";
},
},
});

// Sync actor (timeout shouldn't apply)
const syncActor = actor({
state: { value: 0 },
options: {
action: {
timeout: 50, // 50ms timeout
},
},
actions: {
syncAction: (c) => {
return "sync response";
},
},
});

export const app = setup({
actors: {
shortTimeoutActor,
longTimeoutActor,
defaultTimeoutActor,
syncActor,
},
});

export type App = typeof app;

92 changes: 92 additions & 0 deletions packages/actor-core/fixtures/driver-test-suite/action-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { actor, setup, UserError } from "actor-core";

// Actor with synchronous actions
const syncActor = actor({
state: { value: 0 },
actions: {
// Simple synchronous action that returns a value directly
increment: (c, amount: number = 1) => {
c.state.value += amount;
return c.state.value;
},
// Synchronous action that returns an object
getInfo: (c) => {
return {
currentValue: c.state.value,
timestamp: Date.now(),
};
},
// Synchronous action with no return value (void)
reset: (c) => {
c.state.value = 0;
},
},
});

// Actor with asynchronous actions
const asyncActor = actor({
state: { value: 0, data: null as any },
actions: {
// Async action with a delay
delayedIncrement: async (c, amount: number = 1) => {
await Promise.resolve();
c.state.value += amount;
return c.state.value;
},
// Async action that simulates an API call
fetchData: async (c, id: string) => {
await Promise.resolve();

// Simulate response data
const data = { id, timestamp: Date.now() };
c.state.data = data;
return data;
},
// Async action with error handling
asyncWithError: async (c, shouldError: boolean) => {
await Promise.resolve();

if (shouldError) {
throw new UserError("Intentional error");
}

return "Success";
},
},
});

// Actor with promise actions
const promiseActor = actor({
state: { results: [] as string[] },
actions: {
// Action that returns a resolved promise
resolvedPromise: (c) => {
return Promise.resolve("resolved value");
},
// Action that returns a promise that resolves after a delay
delayedPromise: (c): Promise<string> => {
return new Promise<string>((resolve) => {
c.state.results.push("delayed");
resolve("delayed value");
});
},
// Action that returns a rejected promise
rejectedPromise: (c) => {
return Promise.reject(new UserError("promised rejection"));
},
// Action to check the collected results
getResults: (c) => {
return c.state.results;
},
},
});

export const app = setup({
actors: {
syncActor,
asyncActor,
promiseActor,
},
});

export type App = typeof app;
101 changes: 101 additions & 0 deletions packages/actor-core/fixtures/driver-test-suite/conn-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { actor, setup } from "actor-core";

type ConnState = {
username: string;
role: string;
counter: number;
createdAt: number;
};

const connStateActor = actor({
state: {
sharedCounter: 0,
disconnectionCount: 0,
},
// Define connection state
createConnState: (
c,
{ params }: { params?: { username?: string; role?: string } },
): ConnState => {
return {
username: params?.username || "anonymous",
role: params?.role || "user",
counter: 0,
createdAt: Date.now(),
};
},
// Lifecycle hook when a connection is established
onConnect: (c, conn) => {
// Broadcast event about the new connection
c.broadcast("userConnected", {
id: conn.id,
username: "anonymous",
role: "user",
});
},
// Lifecycle hook when a connection is closed
onDisconnect: (c, conn) => {
c.state.disconnectionCount += 1;
c.broadcast("userDisconnected", {
id: conn.id,
});
},
actions: {
// Action to increment the connection's counter
incrementConnCounter: (c, amount: number = 1) => {
c.conn.state.counter += amount;
},

// Action to increment the shared counter
incrementSharedCounter: (c, amount: number = 1) => {
c.state.sharedCounter += amount;
return c.state.sharedCounter;
},

// Get the connection state
getConnectionState: (c) => {
return { id: c.conn.id, ...c.conn.state };
},

// Check all active connections
getConnectionIds: (c) => {
return c.conns.keys().toArray();
},

// Get disconnection count
getDisconnectionCount: (c) => {
return c.state.disconnectionCount;
},

// Get all active connection states
getAllConnectionStates: (c) => {
return c.conns.entries().map(([id, conn]) => ({ id, ...conn.state })).toArray();
},

// Send message to a specific connection with matching ID
sendToConnection: (c, targetId: string, message: string) => {
if (c.conns.has(targetId)) {
c.conns.get(targetId)!.send("directMessage", { from: c.conn.id, message });
return true;
} else {
return false;
}
},

// Update connection state (simulated for tests)
updateConnection: (
c,
updates: Partial<{ username: string; role: string }>,
) => {
if (updates.username) c.conn.state.username = updates.username;
if (updates.role) c.conn.state.role = updates.role;
return c.conn.state;
},
},
});

export const app = setup({
actors: { connStateActor },
});

export type App = typeof app;
105 changes: 105 additions & 0 deletions packages/actor-core/fixtures/driver-test-suite/error-handling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { actor, setup, UserError } from "actor-core";

const errorHandlingActor = actor({
state: {
errorLog: [] as string[],
},
actions: {
// Action that throws a UserError with just a message
throwSimpleError: () => {
throw new UserError("Simple error message");
},

// Action that throws a UserError with code and metadata
throwDetailedError: () => {
throw new UserError("Detailed error message", {
code: "detailed_error",
metadata: {
reason: "test",
timestamp: Date.now(),
},
});
},

// Action that throws an internal error
throwInternalError: () => {
throw new Error("This is an internal error");
},

// Action that returns successfully
successfulAction: () => {
return "success";
},

// Action that times out (simulated with a long delay)
timeoutAction: async (c) => {
// This action should time out if the timeout is configured
return new Promise((resolve) => {
setTimeout(() => {
resolve("This should not be reached if timeout works");
}, 10000); // 10 seconds
});
},

// Action with configurable delay to test timeout edge cases
delayedAction: async (c, delayMs: number) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`Completed after ${delayMs}ms`);
}, delayMs);
});
},

// Log an error for inspection
logError: (c, error: string) => {
c.state.errorLog.push(error);
return c.state.errorLog;
},

// Get the error log
getErrorLog: (c) => {
return c.state.errorLog;
},

// Clear the error log
clearErrorLog: (c) => {
c.state.errorLog = [];
return true;
},
},
options: {
// Set a short timeout for this actor's actions
action: {
timeout: 500, // 500ms timeout for actions
},
},
});

// Actor with custom timeout
const customTimeoutActor = actor({
state: {},
actions: {
quickAction: async () => {
await new Promise((resolve) => setTimeout(resolve, 50));
return "Quick action completed";
},
slowAction: async () => {
await new Promise((resolve) => setTimeout(resolve, 300));
return "Slow action completed";
},
},
options: {
action: {
timeout: 200, // 200ms timeout
},
},
});

export const app = setup({
actors: {
errorHandlingActor,
customTimeoutActor,
},
});

export type App = typeof app;
Loading
Loading