Sign In
Build with Actors

Lifecycle


Lifecycle Hooks

Lifecycle hooks can be implemented by overriding the following methods of actors.

_onInitialize()

Documentation

Called only once when the actor is first created. This method returns the initial state of the actor (see state documentation).

If you need to call code when the actor is started (e.g. after restarting for upgrading code), see _onStart.

_onStart()

Documentation

This method is called any time the actor is started (e.g. after restarting, upgrading code, or crashing).

This is called after the actor has been initialized but before any connections are accepted.

Use this method to set up any resources or start any background tasks, such as setInterval.

_onStateChange(newState)

Documentation

Called whenever the actor's state changes. This is often used to broadcast state updates.

_onBeforeConnect(opts)

Documentation

Called whenever a new client connects to the actor. Clients can pass parameters when connecting, accessible via opts.parameters.

The returned value becomes the connection's initial state and can be accessed later via connection.state.

Connections cannot interact with the actor until this method completes successfully. Throwing an error will abort the connection. This can be used for authentication - see Authentication for details.

_onConnect(connection)

Documentation

Executed after the client has successfully connected.

Messages will not be processed for this actor until this method succeeds.

Errors thrown from this method will cause the client to disconnect.

_onDisconnect(connection)

Documentation

Called when a client disconnects from the actor. Use this to clean up any connection-specific resources.


Destroying actors

Actors can be shut down gracefully with this._shutdown(). Clients will be gracefully disconnected.

This action is permanent and cannot be reverted.

Actors can also be destroyed externally via the platform API with actors.destroy.


Full Example

interface State {
  count: number;
}

interface ConnParams {
  authToken: string;
}

interface ConnState {
  userId: string;
}

export default class Counter extends Actor<State, ConnParams, ConnState> {
  async _onInitialize(): Promise<State> {
    // Initialize with a count of 0
    return {
      count: 0
    };
  }

  async _onStart(): Promise<void> {
    // Upgrade state if needed
    console.log('Started');
  }

  async _onStateChange(newState: State): Promise<void> {
    // Broadcast the new count to all connected clients
    this._broadcast('countUpdated', {
      count: newState.count
    });
  }

  async _onBeforeConnect(opts: OnBeforeConnectOptions<Counter>): Promise<ConnState> {
    // Validate auth token with your API and determine the user
    const auth = await myValidateAuthToken(opts.parameters.authToken);
    if (!auth) {
      throw new Error('Invalid auth token');
    }

    // Return connection state that will be available as connection.state
    return {
      userId: auth.userId
    };
  }

  async _onConnect(connection: Connection<Counter>): Promise<void> {
    console.log(`User ${connection.state.userId} connected`);
  }

  async _onDisconnect(connection: Connection<Counter>): Promise<void> {
    console.log(`User ${connection.state.userId} disconnected`);
  }

  // Example RPC method
  async increment(rpc: Rpc<Counter>) {
    this._state.count++;
  }
}
TypeScript
Suggest changes to this page