npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@roomkit/worker

v1.3.1

Published

Game logic worker for managing rooms and state in multiplayer games

Downloads

794

Readme

@roomkit/worker

Worker server for the RoomKit framework - manages room state and game logic.

Installation

npm install @roomkit/worker @roomkit/core

Features

  • 🎮 Room Management - Create and manage game rooms with state synchronization
  • 🔄 Message Handling - Type-safe message handling with RoomKit protocol
  • 💾 State Persistence - Optional room state persistence to Redis
  • 🔌 Hot Reload - Seamless room migration between workers
  • ��️ Circuit Breaker - Protection against overload with graceful degradation
  • 📊 Metrics - Built-in Prometheus metrics
  • High Performance - Optimized for low-latency multiplayer games

Quick Start

1. Define Your Room

import { Room } from '@roomkit/worker';

interface GameState {
  players: Map<string, Player>;
  score: number;
}

class GameRoom extends Room<GameState> {
  maxClients = 4;

  onCreate(options: any) {
    this.setState({
      players: new Map(),
      score: 0,
    });
  }

  onJoin(client: Client, options?: any) {
    this.state.players.set(client.sessionId, {
      name: options.name,
      x: 0,
      y: 0,
    });
    this.broadcast('player-joined', { id: client.sessionId });
  }

  onMessage(client: Client, type: string, payload: any) {
    if (type === 'move') {
      const player = this.state.players.get(client.sessionId);
      if (player) {
        player.x = payload.x;
        player.y = payload.y;
        this.broadcast('player-moved', { id: client.sessionId, ...payload });
      }
    }
  }

  onLeave(client: Client, consented: boolean) {
    this.state.players.delete(client.sessionId);
    this.broadcast('player-left', { id: client.sessionId });
  }
}

2. Start the Worker

import { createWorker, Room } from '@roomkit/worker';

class GameRoom extends Room<GameState> { /* ... */ }

const worker = await createWorker({
  redis: 'redis://localhost:6379',
  rooms: [
    { name: 'game', room: GameRoom }
  ],
  admin: { 
    port: 28200 
  },
});

await worker.listen();
console.log(\`Worker listening on admin port \${worker.adminPort}\`);

Configuration

Redis Configuration

// Option 1: URL string
redis: 'redis://:password@localhost:6379/0'

// Option 2: Object
redis: {
  host: 'localhost',
  port: 6379,
  password: 'your-password',
  db: 0
}

Room Registration

rooms: [
  { 
    name: 'lobby',      // Room type name
    room: LobbyRoom     // Room class
  },
  { 
    name: 'game', 
    room: GameRoom 
  },
]

Circuit Breaker

circuitBreaker: {
  maxRooms: 1000,              // Max rooms per worker (default: 1000)
  maxPendingRequests: 100,     // Max pending room creation requests (default: 100)
  enabled: true,               // Enable circuit breaker (default: true)
  failureThreshold: 5,         // Failures before opening (default: 5)
  successThreshold: 2,         // Successes before closing (default: 2)
  timeout: 10000,              // Timeout in ms (default: 10000)
  resetTimeout: 30000,         // Reset timeout in ms (default: 30000)
}

State Persistence

persistence: {
  enabled: true,              // Enable persistence (default: false)
  saveInterval: 5000,         // Auto-save interval in ms (default: 5000)
  loadOnCreate: true,         // Load state on room creation (default: true)
}

Admin API

admin: {
  port: 28200,       // Admin API port (default: 28200)
  enabled: true      // Enable admin API (default: true)
}

Complete Example

import { createWorker, Room } from '@roomkit/worker';
import { LobbyRoom } from './rooms/LobbyRoom';

class GameRoom extends Room<GameState> { /* ... */ }

const worker = await createWorker({
  // Optional: Custom worker ID (auto-generated if not provided)
  id: 'worker-1',
  
  // Redis configuration (required)
  redis: {
    host: process.env.REDIS_HOST || 'localhost',
    port: parseInt(process.env.REDIS_PORT || '6379'),
    password: process.env.REDIS_PASSWORD,
  },
  
  // Room definitions (required)
  rooms: [
    { name: 'lobby', room: LobbyRoom },
    { name: 'game', room: GameRoom },
  ],
  
  // Circuit breaker configuration
  circuitBreaker: {
    maxRooms: 1000,
    maxPendingRequests: 100,
    enabled: true,
    failureThreshold: 5,
    successThreshold: 2,
    timeout: 10000,
    resetTimeout: 30000,
  },
  
  // State persistence
  persistence: {
    enabled: true,
    saveInterval: 5000,
    loadOnCreate: true,
  },
  
  // Admin API
  admin: {
    port: 28200,
    enabled: true,
  },
});

// Start the worker
await worker.listen();

// Graceful shutdown
process.on('SIGTERM', async () => {
  await worker.close();
  process.exit(0);
});

Room Lifecycle

class MyRoom extends Room<MyState> {
  // Called when room is created
  onCreate(options: any) {
    this.setState({ ... });
  }

  // Called when a client joins
  onJoin(client: Client, options?: any) {
    // Add player to state
  }

  // Called when client sends a message
  onMessage(client: Client, type: string, payload: any) {
    // Handle game logic
  }

  // Called when a client leaves
  onLeave(client: Client, consented: boolean) {
    // Remove player from state
  }

  // Called before room is destroyed
  onDispose() {
    // Cleanup resources
  }
}

Room API

Broadcasting

// Broadcast to all clients
this.broadcast('event-type', { data: 'value' });

// Broadcast to all except one
this.broadcast('event-type', { data: 'value' }, { except: client });

// Send to specific client
client.send('event-type', { data: 'value' });

State Management

// Set initial state
this.setState({ score: 0, players: new Map() });

// Update state (triggers automatic sync to clients)
this.state.score += 10;
this.state.players.set(id, player);

// Lock for atomic updates
this.lock.acquire('update-score', async () => {
  this.state.score += 10;
});

Room Metadata

// Set custom metadata (visible in lobby)
this.setMetadata({ 
  mapName: 'Forest',
  difficulty: 'Hard'
});

// Set if room is private
this.setPrivate(true);

Environment Variables

The worker supports basic environment variables for infrastructure configuration:

# Redis (infrastructure)
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your-password

# Note: Application-level configs (circuit breaker, persistence, etc.) 
# should be passed via code parameters for better type safety.

Admin API

Health Check

GET http://localhost:28200/health

Metrics

GET http://localhost:28200/metrics

Room Stats

GET http://localhost:28200/admin/rooms

Docker

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 28200
CMD ["node", "worker.js"]
docker run -p 28200:28200 \
  -e REDIS_HOST=redis \
  -e REDIS_PORT=6379 \
  my-worker

Production Deployment

Horizontal Scaling

Run multiple worker instances:

# Worker 1
node worker.js --id worker-1

# Worker 2
node worker.js --id worker-2

# Workers register automatically via Redis

Monitoring

  • Monitor room count, client count, message rate
  • Set up alerts for circuit breaker triggers
  • Track room creation/disposal rates

Best Practices

  1. Set maxRooms based on your server capacity
  2. Enable persistence for important game state
  3. Use circuit breaker to prevent overload
  4. Implement proper cleanup in onDispose()
  5. Handle errors gracefully in onMessage()

License

MIT