### Kubernetes Container Probe Configuration Source: https://github.com/gajus/lightship/blob/main/README.md Example Kubernetes probe configurations for readiness, liveness, and startup probes using Lightship's default ports. ```APIDOC ### Kubernetes container probe configuration This is an example of a reasonable [container probe](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes) configuration to use with Lightship. ```yaml readinessProbe: httpGet: path: /ready port: 9000 failureThreshold: 1 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 5 livenessProbe: httpGet: path: /live port: 9000 failureThreshold: 3 initialDelaySeconds: 10 # Allow sufficient amount of time (90 seconds = periodSeconds * failureThreshold) # for the registered shutdown handlers to run to completion. periodSeconds: 30 successThreshold: 1 # Setting a very low timeout value (e.g. 1 second) can cause false-positive # checks and service interruption. timeoutSeconds: 5 # As per Kubernetes documentation (https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#when-should-you-use-a-startup-probe), # startup probe should point to the same endpoint as the liveness probe. # # Startup probe is only needed when container is taking longer to start than # `initialDelaySeconds + failureThreshold × periodSeconds` of the liveness probe. startupProbe: httpGet: path: /live port: 9000 failureThreshold: 3 initialDelaySeconds: 10 periodSeconds: 30 successThreshold: 1 timeoutSeconds: 5 ``` ``` -------------------------------- ### Beacon Log Example Source: https://github.com/gajus/lightship/blob/main/README.md Example of a log message indicating that program termination is on hold due to live beacons. The log includes beacon context. ```json {"context":{"package":"lightship","namespace":"factories/createLightship","logLevel":30,"beacons":[{"context":{"id":1}}]},"message":"program termination is on hold because there are live beacons","sequence":2,"time":1563892493825,"version":"1.0.0"} ``` -------------------------------- ### Kubernetes Container Probe Configuration Source: https://github.com/gajus/lightship/blob/main/README.md Example Kubernetes container probe configuration for readiness, liveness, and startup probes. These probes use HTTP GET requests to check the application's health and lifecycle status. ```yaml readinessProbe: httpGet: path: /ready port: 9000 failureThreshold: 1 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 5 livenessProbe: httpGet: path: /live port: 9000 failureThreshold: 3 initialDelaySeconds: 10 # Allow sufficient amount of time (90 seconds = periodSeconds * failureThreshold) # for the registered shutdown handlers to run to completion. periodSeconds: 30 successThreshold: 1 # Setting a very low timeout value (e.g. 1 second) can cause false-positive # checks and service interruption. timeoutSeconds: 5 # As per Kubernetes documentation (https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#when-should-you-use-a-startup-probe), # startup probe should point to the same endpoint as the liveness probe. # # Startup probe is only needed when container is taking longer to start than # `initialDelaySeconds + failureThreshold × periodSeconds` of the liveness probe. startupProbe: httpGet: path: /live port: 9000 failureThreshold: 3 initialDelaySeconds: 10 periodSeconds: 30 successThreshold: 1 timeoutSeconds: 5 ``` -------------------------------- ### Kubernetes Health Check Failure Example Source: https://github.com/gajus/lightship/blob/main/README.md Example log messages showing intermittent Liveness and Readiness probe failures in Kubernetes, often caused by event-loop blocking tasks. ```text Warning Unhealthy 4m17s (x3 over 4m27s) kubelet, f95a4d94-jwfr Liveness probe failed: Get http://10.24.7.155:9000/live: net/http: request canceled (Client.Timeout exceeded while awaiting headers) Warning Unhealthy 3m28s (x15 over 4m38s) kubelet, f95a4d94-jwfr Readiness probe failed: Get http://10.24.7.155:9000/ready: net/http: request canceled (Client.Timeout exceeded while awaiting headers) ``` -------------------------------- ### Create Lightship Instance Source: https://context7.com/gajus/lightship/llms.txt Initializes and starts a Lightship instance. Configure port, Kubernetes detection, shutdown timeouts, and custom termination functions. The server listens on port 9000 by default or a random port in local mode. ```typescript import { createLightship } from 'lightship'; // Basic usage with default configuration const lightship = await createLightship(); // With custom configuration const lightship = await createLightship({ port: 9000, // HTTP server port (default: 9000, env: LIGHTSHIP_PORT) detectKubernetes: true, // Auto-detect Kubernetes environment (default: true) gracefulShutdownTimeout: 30000, // Max time for graceful shutdown in ms (default: 30000) shutdownDelay: 5000, // Delay before shutdown handlers run in ms (default: 5000) shutdownHandlerTimeout: 5000, // Max time for shutdown handlers in ms (default: 5000) signals: ['SIGTERM', 'SIGHUP', 'SIGINT'], // Signals that trigger shutdown terminate: () => process.exit(1) // Custom termination function }); // Server is now listening and ready to accept probe requests console.log('Lightship server started'); ``` -------------------------------- ### Shutdown Server After 1000 Requests Source: https://github.com/gajus/lightship/blob/main/README.md Configures Lightship to initiate a shutdown sequence after the server has responded to 1000 requests. It also includes rate limiting logic similar to the previous example. ```javascript import express from 'express'; import delay from 'delay'; import { createLightship } from 'lightship'; const app = express(); const minute = 60 * 1000; let total = 0; let runningTotal = 0; app.get('/', (req, res) => { total++; runningTotal++; if (total === 1000) { lightship.shutdown(); } setTimeout(() => { runningTotal--; if (runningTotal < 100) { lightship.signalReady(); } else { lightship.signalNotReady(); } }, minute); res.send('Hello, World!'); }); const server = app.listen(8080); const lightship = await createLightship(); lightship.registerShutdownHandler(async () => { // Allow sufficient amount of time to allow all of the existing // HTTP requests to finish before terminating the service. await delay(minute); server.close(); }); // Lightship default state is "SERVER_IS_NOT_READY". Therefore, you must signal // that the server is now ready to accept connections. lightship.signalReady(); ``` -------------------------------- ### Express.js Server with Lightship Integration Source: https://github.com/gajus/lightship/blob/main/README.md Integrates Lightship into an Express.js application to signal server readiness and handle shutdown. Ensure to call `lightship.signalReady()` after the server starts listening. ```javascript import express from 'express'; import { createLightship } from 'lightship'; const app = express(); app.get('/', (req, res) => { res.send('Hello, World!'); }); const server = app .listen(8080, () => { // Lightship default state is "SERVER_IS_NOT_READY". Therefore, you must signal // that the server is now ready to accept connections. lightship.signalReady(); }) .on('error', () => { lightship.shutdown(); });; const lightship = await createLightship(); lightship.registerShutdownHandler(() => { server.close(); }); ``` -------------------------------- ### Initiate Graceful Shutdown Source: https://context7.com/gajus/lightship/llms.txt Starts the graceful shutdown sequence. The server state changes to SERVER_IS_SHUTTING_DOWN, followed by a delay, waiting for beacons, and executing shutdown handlers. The process exits after handlers complete or a timeout occurs. ```typescript import express from 'express'; import { createLightship } from 'lightship'; const app = express(); const lightship = await createLightship(); let totalRequests = 0; const MAX_REQUESTS = 1000; app.get('/', (req, res) => { totalRequests++; // Shutdown after serving maximum requests if (totalRequests >= MAX_REQUESTS) { lightship.shutdown(); } res.send('Hello, World!'); }); const server = app.listen(8080, () => { lightship.signalReady(); }); lightship.registerShutdownHandler(async () => { // Allow in-flight requests to complete await new Promise(resolve => setTimeout(resolve, 5000)); server.close(); console.log(`Server shutdown after ${totalRequests} requests`); }); ``` -------------------------------- ### createLightship Source: https://context7.com/gajus/lightship/llms.txt The main factory function that creates and starts a Lightship instance. It initializes an HTTP server with health check endpoints and returns an object with methods to control service readiness state and shutdown behavior. ```APIDOC ## createLightship ### Description Creates and starts a Lightship instance, initializing an HTTP server with health check endpoints. ### Method `createLightship(options?: LightshipOptions): Promise ### Parameters #### Options - **port** (number) - Optional - HTTP server port (default: 9000, env: LIGHTSHIP_PORT) - **detectKubernetes** (boolean) - Optional - Auto-detect Kubernetes environment (default: true) - **gracefulShutdownTimeout** (number) - Optional - Max time for graceful shutdown in ms (default: 30000) - **shutdownDelay** (number) - Optional - Delay before shutdown handlers run in ms (default: 5000) - **shutdownHandlerTimeout** (number) - Optional - Max time for shutdown handlers in ms (default: 5000) - **signals** (string[]) - Optional - Signals that trigger shutdown - **terminate** (function) - Optional - Custom termination function ### Request Example ```typescript import { createLightship } from 'lightship'; // Basic usage with default configuration const lightship = await createLightship(); // With custom configuration const lightship = await createLightship({ port: 9000, detectKubernetes: true, gracefulShutdownTimeout: 30000, shutdownDelay: 5000, shutdownHandlerTimeout: 5000, signals: ['SIGTERM', 'SIGHUP', 'SIGINT'], terminate: () => process.exit(1) }); ``` ### Response #### Success Response (200) - **lightship** (object) - An object with methods to control service readiness state and shutdown behavior. #### Response Example ```typescript // lightship object with methods like signalReady, signalNotReady, shutdown, etc. console.log('Lightship server started'); ``` ``` -------------------------------- ### Event Loop Blocking Task Example Source: https://github.com/gajus/lightship/blob/main/README.md Demonstrates an event-loop blocking task that can cause health checks to fail intermittently. This task blocks the event loop for several seconds. ```javascript const startTime = Date.now(); let index0 = 1000; while (index0--) { let index1 = 1000; while (index1--) { console.log(index0 + ':' + index1); } } console.log(Date.now() - startTime); ``` -------------------------------- ### Wait for Service Ready State in TypeScript Source: https://context7.com/gajus/lightship/llms.txt Returns a promise that resolves the first time the service transitions to ready state. This is useful for triggering actions that depend on the service being fully initialized, like running integration tests or starting background workers. ```typescript import { createLightship } from 'lightship'; const lightship = await createLightship(); // Queue initialization tasks lightship.queueBlockingTask(initializeDatabase()); lightship.queueBlockingTask(connectToMessageBroker()); const server = app.listen(8080, () => { lightship.signalReady(); }); // Wait for service to be fully ready await lightship.whenFirstReady(); // Now safe to start background workers console.log('Service ready, starting background workers'); startBackgroundWorkers(); // Or run integration tests in development if (process.env.NODE_ENV === 'development') { await runIntegrationTests(); } ``` -------------------------------- ### Create Lightship Instance Source: https://github.com/gajus/lightship/blob/main/README.md Demonstrates how to create an instance of Lightship with optional configuration. ```APIDOC ## Usage Use `createLightship` to create an instance of Lightship. ```js import { createLightship } from 'lightship'; const configuration = {}; const lightship = await createLightship(configuration); ``` The following types describe the configuration shape and the resulting Lightship instance interface. ### ConfigurationInput Type ```js /** * @property detectKubernetes Run Lightship in local mode when Kubernetes is not detected. Default: true. * @property gracefulShutdownTimeout A number of milliseconds before forcefull termination if process does not gracefully exit. The timer starts when `lightship.shutdown()` is called. This includes the time allowed to live beacons. Default: 30000. * @property port The port on which the Lightship service listens. This port must be different than your main service port, if any. The default port is 9000. The default can be overwritten using LIGHTSHIP_PORT environment variable. * @property shutdownDelay Delays the shutdown handler by X milliseconds. This value should match `readinessProbe.periodSeconds`. Default 5000. * @property shutdownHandlerTimeout A number of milliseconds before forcefull termination if shutdown handlers do not complete. The timer starts when the first shutdown handler is called. Default: 5000. * @property signals An a array of [signal events](https://nodejs.org/api/process.html#process_signal_events). Default: [SIGTERM]. * @property terminate Method used to terminate Node.js process. Default: `() => { process.exit(1) };`. */ export type ConfigurationInput = {| +detectKubernetes?: boolean, +gracefulShutdownTimeout?: number, +port?: number, +shutdownDelay?: number, +shutdownHandlerTimeout?: number, +signals?: $ReadOnlyArray, +terminate?: () => void, |}; ``` ### Lightship Instance Interface ```js /** * @property queueBlockingTask Forces service state to SERVER_IS_NOT_READY until all promises are resolved. * @property registerShutdownHandler Registers teardown functions that are called when shutdown is initialized. All registered shutdown handlers are executed in the order they have been registered. After all shutdown handlers have been executed, Lightship asks `process.exit()` to terminate the process synchronously. * @property shutdown Changes server state to SERVER_IS_SHUTTING_DOWN and initialises the shutdown of the application. * @property signalNotReady Changes server state to SERVER_IS_NOT_READY. * @property signalReady Changes server state to SERVER_IS_READY. * @property whenFirstReady Resolves the first time the service goes from `SERVER_IS_NOT_READY` to `SERVER_IS_READY` state. */ type Lightship = {| +createBeacon: (context?: BeaconContext) => BeaconController, +isServerReady: () => boolean, +isServerShuttingDown: () => boolean, +queueBlockingTask: (blockingTask: Promise) => void, +registerShutdownHandler: (shutdownHandler: ShutdownHandler) => void, +server: http$Server, +shutdown: () => Promise, +signalNotReady: () => void, +signalReady: () => void, +whenFirstReady: () => Promise, |}; ``` ``` -------------------------------- ### Logging Configuration Source: https://github.com/gajus/lightship/blob/main/README.md Instructions on how to enable logging for Lightship. ```APIDOC ### Logging `lightship` is using [Roarr](https://github.com/gajus/roarr) to implement logging. Set `ROARR_LOG=true` environment variable to enable logging. ``` -------------------------------- ### Create Lightship Instance Source: https://github.com/gajus/lightship/blob/main/README.md Use `createLightship` to instantiate Lightship. This function is asynchronous and requires configuration options. ```javascript import { createLightship } from 'lightship'; const configuration: ConfigurationInput = {}; const lightship: Lightship = await createLightship(configuration); ``` -------------------------------- ### Basic Express.js Server Source: https://github.com/gajus/lightship/blob/main/README.md A simple Express.js server that responds with 'Hello, World!'. This serves as a base for integrating Lightship. ```javascript import express from 'express'; const app = express(); app.get('/', (req, res) => { res.send('Hello, World!'); }); app.listen(8080); ``` -------------------------------- ### Wait for Server Readiness with Lightship Source: https://github.com/gajus/lightship/blob/main/README.md Use `whenFirstReady` to execute tasks only after the service has transitioned to the `SERVER_IS_READY` state for the first time. The promise resolves only once. ```javascript import express from 'express'; import { createLightship } from 'lightship'; const lightship = await createLightship(); const app = express(); app.get('/', (req, res) => { res.send('Hello, World!'); }); const server = app.listen(8080, () => { lightship.signalReady(); }); (async () => { // `whenFirstReady` returns a promise that is resolved the first time that // the service goes from `SERVER_IS_NOT_READY` to `SERVER_IS_READY` state. await lightship.whenFirstReady(); await runIntegrationTests(); })(); ``` -------------------------------- ### Create a Lightship Beacon Source: https://github.com/gajus/lightship/blob/main/README.md Use `createBeacon()` to create a beacon. Beacons suspend shutdown handlers until they are dead. ```javascript const lightship = await createLightship(); const beacon = lightship.createBeacon(); ``` -------------------------------- ### Test Lightship Health Endpoints Locally Source: https://context7.com/gajus/lightship/llms.txt Use curl to test the /health, /ready, and /live endpoints provided by Lightship. These commands help verify the server's readiness and liveness status. ```bash # Testing health endpoints locally curl http://localhost:9000/health # SERVER_IS_NOT_READY (500) or SERVER_IS_READY (200) or SERVER_IS_SHUTTING_DOWN (500) curl http://localhost:9000/ready # SERVER_IS_NOT_READY (500) or SERVER_IS_READY (200) curl http://localhost:9000/live # SERVER_IS_NOT_SHUTTING_DOWN (200) or SERVER_IS_SHUTTING_DOWN (500) ``` -------------------------------- ### Check Server State with Lightship Source: https://context7.com/gajus/lightship/llms.txt Use isServerReady() and isServerShuttingDown() to monitor and control server lifecycle. signalReady() must be called for isServerReady() to return true. isServerShuttingDown() becomes true after shutdown() is invoked or a shutdown signal is received. ```typescript import { createLightship } from 'lightship'; const lightship = await createLightship(); // State checks during lifecycle console.log(lightship.isServerReady()); // false - initial state console.log(lightship.isServerShuttingDown()); // false - not shutting down lightship.signalReady(); console.log(lightship.isServerReady()); // true - ready for traffic // Use in request handlers to reject new work during shutdown app.post('/jobs', (req, res) => { if (lightship.isServerShuttingDown()) { return res.status(503).json({ error: 'Service is shutting down, please retry with another instance' }); } // Accept and process the job queueJob(req.body); res.status(202).json({ status: 'accepted' }); }); ``` -------------------------------- ### Create Beacon with Context Source: https://github.com/gajus/lightship/blob/main/README.md Provide context to a beacon, such as a `jobId`, for better logging and identification. This is useful when managing job queues. ```javascript for (const job of jobs) { if (lightship.isServerShuttingDown()) { log.info('detected that the service is shutting down; terminating the event loop'); break; } const beacon = lightship.createBeacon({ jobId: job.id }); // Do the job. await beacon.die(); } ``` -------------------------------- ### shutdown Source: https://context7.com/gajus/lightship/llms.txt Initiates the graceful shutdown sequence. Changes server state to `SERVER_IS_SHUTTING_DOWN`, waits for the configured `shutdownDelay`, waits for all beacons to die, then executes registered shutdown handlers in order. ```APIDOC ## shutdown ### Description Initiates the graceful shutdown sequence for the service. ### Method `lightship.shutdown(): Promise` ### Request Example ```typescript import express from 'express'; import { createLightship } from 'lightship'; const app = express(); const lightship = await createLightship(); let totalRequests = 0; const MAX_REQUESTS = 1000; app.get('/', (req, res) => { totalRequests++; // Shutdown after serving maximum requests if (totalRequests >= MAX_REQUESTS) { lightship.shutdown(); } res.send('Hello, World!'); }); const server = app.listen(8080, () => { lightship.signalReady(); }); lightship.registerShutdownHandler(async () => { // Allow in-flight requests to complete await new Promise(resolve => setTimeout(resolve, 5000)); server.close(); console.log(`Server shutdown after ${totalRequests} requests`); }); ``` ### Response #### Success Response (200) No direct response body, the process will exit after shutdown handlers complete. #### Response Example ``` // Process exits after graceful shutdown. ``` ``` -------------------------------- ### signalReady Source: https://context7.com/gajus/lightship/llms.txt Signals that the service is ready to accept traffic. This changes the server state to `SERVER_IS_READY`, causing the `/ready` and `/health` endpoints to return HTTP 200. This method should be called after your application has completed initialization. ```APIDOC ## signalReady ### Description Signals that the service is ready to accept traffic, updating the server state to `SERVER_IS_READY`. ### Method `lightship.signalReady(): void` ### Request Example ```typescript import express from 'express'; import { createLightship } from 'lightship'; const app = express(); const lightship = await createLightship(); const server = app.listen(8080, () => { // Signal ready only after the Express server is listening lightship.signalReady(); console.log('Server ready and accepting connections'); }); // Register cleanup for graceful shutdown lightship.registerShutdownHandler(() => { server.close(); }); ``` ### Response #### Success Response (200) No direct response body, but the server state is updated. #### Response Example ``` // Server state updated internally. ``` ``` -------------------------------- ### Lightship Configuration Types Source: https://github.com/gajus/lightship/blob/main/README.md TypeScript types for Lightship configuration and the Lightship instance interface. These define the available options for customizing Lightship's behavior. ```typescript /** * A teardown function called when shutdown is initialized. */ type ShutdownHandler = () => Promise | void; /** * @property detectKubernetes Run Lightship in local mode when Kubernetes is not detected. Default: true. * @property gracefulShutdownTimeout A number of milliseconds before forcefull termination if process does not gracefully exit. The timer starts when `lightship.shutdown()` is called. This includes the time allowed to live beacons. Default: 30000. * @property port The port on which the Lightship service listens. This port must be different than your main service port, if any. The default port is 9000. The default can be overwritten using LIGHTSHIP_PORT environment variable. * @property shutdownDelay Delays the shutdown handler by X milliseconds. This value should match `readinessProbe.periodSeconds`. Default 5000. * @property shutdownHandlerTimeout A number of milliseconds before forcefull termination if shutdown handlers do not complete. The timer starts when the first shutdown handler is called. Default: 5000. * @property signals An a array of [signal events]{@link https://nodejs.org/api/process.html#process_signal_events}. Default: [SIGTERM]. * @property terminate Method used to terminate Node.js process. Default: `() => { process.exit(1) };`. */ export type ConfigurationInput = {| +detectKubernetes?: boolean, +gracefulShutdownTimeout?: number, +port?: number, +shutdownDelay?: number, +shutdownHandlerTimeout?: number, +signals?: $ReadOnlyArray, +terminate?: () => void, |}; /** * @property queueBlockingTask Forces service state to SERVER_IS_NOT_READY until all promises are resolved. * @property registerShutdownHandler Registers teardown functions that are called when shutdown is initialized. All registered shutdown handlers are executed in the order they have been registered. After all shutdown handlers have been executed, Lightship asks `process.exit()` to terminate the process synchronously. * @property shutdown Changes server state to SERVER_IS_SHUTTING_DOWN and initialises the shutdown of the application. * @property signalNotReady Changes server state to SERVER_IS_NOT_READY. * @property signalReady Changes server state to SERVER_IS_READY. * @property whenFirstReady Resolves the first time the service goes from `SERVER_IS_NOT_READY` to `SERVER_IS_READY` state. */ type Lightship = {| +createBeacon: (context?: BeaconContext) => BeaconController, +isServerReady: () => boolean, +isServerShuttingDown: () => boolean, +queueBlockingTask: (blockingTask: Promise) => void, +registerShutdownHandler: (shutdownHandler: ShutdownHandler) => void, +server: http$Server, +shutdown: () => Promise, +signalNotReady: () => void, +signalReady: () => void, +whenFirstReady: () => Promise, |}; ``` -------------------------------- ### Create Beacon for In-flight Work in TypeScript Source: https://context7.com/gajus/lightship/llms.txt Create beacons to track in-flight work, delaying shutdown handlers until explicitly killed. The shutdown sequence waits for all beacons to call `die()` before running shutdown handlers. This is useful for processing queue jobs. ```typescript import { createLightship } from 'lightship'; const lightship = await createLightship(); async function processJobQueue(jobs: Job[]) { for (const job of jobs) { // Check if shutdown was requested if (lightship.isServerShuttingDown()) { console.log('Shutdown requested, stopping job processing'); break; } // Create beacon to track this job const beacon = lightship.createBeacon({ jobId: job.id, jobType: job.type }); try { await processJob(job); console.log(`Job ${job.id} completed`); } finally { // Always kill beacon when done (success or failure) await beacon.die(); } } } lightship.registerShutdownHandler(() => { console.log('All jobs completed, shutting down'); }); lightship.signalReady(); await processJobQueue(jobs); ``` -------------------------------- ### Kubernetes Health Check Endpoints Configuration Source: https://context7.com/gajus/lightship/llms.txt Configure Kubernetes probes to use Lightship's /health, /ready, and /live endpoints. The /health endpoint reflects overall service health, /ready is for readiness probes, and /live is for liveness probes. ```yaml # Kubernetes deployment configuration apiVersion: apps/v1 kind: Deployment metadata: name: my-service spec: template: spec: containers: - name: app ports: - containerPort: 8080 # Application port - containerPort: 9000 # Lightship health check port readinessProbe: httpGet: path: /ready port: 9000 initialDelaySeconds: 5 periodSeconds: 5 failureThreshold: 1 livenessProbe: httpGet: path: /live port: 9000 initialDelaySeconds: 10 periodSeconds: 30 failureThreshold: 3 startupProbe: httpGet: path: /live port: 9000 initialDelaySeconds: 10 periodSeconds: 30 failureThreshold: 3 ``` -------------------------------- ### Queue Blocking Tasks with Lightship Source: https://github.com/gajus/lightship/blob/main/README.md Use `queueBlockingTask` to queue promises that must resolve before the service is considered ready. Lightship status remains `SERVER_IS_NOT_READY` until all queued tasks are resolved and `signalReady` is called. ```javascript import express from 'express'; import { createLightship } from 'lightship'; const lightship = await createLightship(); lightship.queueBlockingTask(new Promise((resolve) => { setTimeout(() => { // Lightship service status will be `SERVER_IS_NOT_READY` until all promises // submitted to `queueBlockingTask` are resolved. resolve(); }, 1000); })); const app = express(); app.get('/', (req, res) => { res.send('Hello, World!'); }); const server = app.listen(8080, () => { // All signals will be queued until after all blocking tasks are resolved. lightship.signalReady(); }); ``` -------------------------------- ### Detecting Node.js Process Leaks Source: https://github.com/gajus/lightship/blob/main/README.md Integrate `why-is-node-running` into a Lightship shutdown handler to log active handles and requests when the process fails to exit. This helps diagnose issues keeping the event loop active. ```javascript import whyIsNodeRunning from 'why-is-node-running'; import express from 'express'; import { createLightship } from 'lightship'; const app = express(); app.get('/', (req, res) => { res.send('Hello, World!'); }); const server = app.listen(8080); const lightship = await createLightship(); lightship.registerShutdownHandler(() => { server.close(); whyIsNodeRunning(); }); lightship.signalReady(); ``` -------------------------------- ### Rate Limiting with Lightship Signal Source: https://github.com/gajus/lightship/blob/main/README.md Implements a rate-limiting mechanism using Lightship's `signalReady` and `signalNotReady` methods. The server becomes unready if requests exceed 100 per minute. ```javascript import express from 'express'; import { createLightship } from 'lightship'; const app = express(); const minute = 60 * 1000; let runningTotal = 0; app.get('/', (req, res) => { runningTotal++; setTimeout(() => { runningTotal--; if (runningTotal < 100) { lightship.signalReady(); } else { lightship.signalNotReady(); } }, minute); res.send('Hello, World!'); }); const server = app.listen(8080); const lightship = await createLightship(); lightship.registerShutdownHandler(() => { server.close(); }); // Lightship default state is "SERVER_IS_NOT_READY". Therefore, you must signal // that the server is now ready to accept connections. lightship.signalReady(); ``` -------------------------------- ### Signal Service Readiness Source: https://context7.com/gajus/lightship/llms.txt Signals that the service is ready to accept traffic by changing the server state to SERVER_IS_READY. This makes /ready and /health endpoints return HTTP 200. Call this after application initialization is complete. ```typescript import express from 'express'; import { createLightship } from 'lightship'; const app = express(); app.get('/', (req, res) => { res.send('Hello, World!'); }); const lightship = await createLightship(); const server = app.listen(8080, () => { // Signal ready only after the Express server is listening lightship.signalReady(); console.log('Server ready and accepting connections'); }); // Register cleanup for graceful shutdown lightship.registerShutdownHandler(() => { server.close(); }); ``` -------------------------------- ### signalNotReady Source: https://context7.com/gajus/lightship/llms.txt Changes the server state to `SERVER_IS_NOT_READY`, causing `/ready` and `/health` endpoints to return HTTP 500. Use this to temporarily remove the service from the load balancer pool. ```APIDOC ## signalNotReady ### Description Signals that the service is not ready to accept traffic, updating the server state to `SERVER_IS_NOT_READY`. ### Method `lightship.signalNotReady(): void` ### Request Example ```typescript import express from 'express'; import { createLightship } from 'lightship'; const app = express(); const lightship = await createLightship(); let requestCount = 0; const RATE_LIMIT = 100; app.get('/', (req, res) => { requestCount++; // Apply backpressure when rate limit is exceeded if (requestCount >= RATE_LIMIT) { lightship.signalNotReady(); } res.send('Hello, World!'); }); // Reset counter and restore readiness periodically setInterval(() => { requestCount = 0; if (!lightship.isServerShuttingDown()) { lightship.signalReady(); } }, 60000); app.listen(8080, () => { lightship.signalReady(); }); ``` ### Response #### Success Response (200) No direct response body, but the server state is updated. #### Response Example ``` // Server state updated internally. ``` ``` -------------------------------- ### Queue Blocking Tasks for Initialization in TypeScript Source: https://context7.com/gajus/lightship/llms.txt Queue promises that must resolve before the service becomes ready. The service remains in `SERVER_IS_NOT_READY` state until all blocking tasks complete. Use this for initialization tasks like cache warming or establishing upstream connections. ```typescript import express from 'express'; import { createLightship } from 'lightship'; const lightship = await createLightship(); const app = express(); // Queue cache warming as a blocking task lightship.queueBlockingTask( warmCache().then(() => { console.log('Cache warmed successfully'); }) ); // Queue database migration check lightship.queueBlockingTask( checkDatabaseMigrations().then(() => { console.log('Database migrations verified'); }) ); app.get('/data', async (req, res) => { const data = await getFromCache(req.query.key); res.json(data); }); const server = app.listen(8080, () => { // Service won't be ready until both blocking tasks complete lightship.signalReady(); }); // If any blocking task rejects, shutdown is triggered automatically ``` -------------------------------- ### Manage Job Queue with Beacons Source: https://github.com/gajus/lightship/blob/main/README.md Use beacons to suspend the shutdown handler while processing a job queue. Check `isServerShuttingDown()` to break the loop if shutdown is initiated. ```javascript for (const job of jobs) { if (lightship.isServerShuttingDown()) { log.info('detected that the service is shutting down; terminating the event loop'); break; } const beacon = lightship.createBeacon(); // Do the job. await beacon.die(); } ``` -------------------------------- ### Signal Service Unreadiness Source: https://context7.com/gajus/lightship/llms.txt Changes the server state to SERVER_IS_NOT_READY, causing /ready and /health endpoints to return HTTP 500. Use this to temporarily remove the service from load balancing during maintenance or resource issues. ```typescript import express from 'express'; import { createLightship } from 'lightship'; const app = express(); const lightship = await createLightship(); const RATE_LIMIT = 100; const WINDOW_MS = 60000; let requestCount = 0; app.get('/', (req, res) => { requestCount++; // Apply backpressure when rate limit is exceeded if (requestCount >= RATE_LIMIT) { lightship.signalNotReady(); } res.send('Hello, World!'); }); // Reset counter and restore readiness periodically setInterval(() => { requestCount = 0; if (!lightship.isServerShuttingDown()) { lightship.signalReady(); } }, WINDOW_MS); app.listen(8080, () => { lightship.signalReady(); }); ``` -------------------------------- ### Signal a Beacon is Dead Source: https://github.com/gajus/lightship/blob/main/README.md Use the `die()` method on a beacon to signal that it is no longer active. A beacon cannot be revived after it has died. ```javascript beacon.die(); // This beacon is now dead. ``` -------------------------------- ### Register Shutdown Handlers in TypeScript Source: https://context7.com/gajus/lightship/llms.txt Register teardown functions that execute sequentially during shutdown. Use this for closing connections, flushing buffers, and cleaning up resources. Handlers run after the shutdown delay and after all beacons have died. ```typescript import { createLightship } from 'lightship'; import { createPool } from 'mysql2/promise'; const lightship = await createLightship(); // Database connection pool const pool = createPool({ host: 'localhost', user: 'root', database: 'myapp' }); // Redis client const redis = new Redis(); // HTTP server const server = app.listen(8080); // Register handlers in order of dependency (reverse of initialization) lightship.registerShutdownHandler(() => { console.log('Closing HTTP server...'); server.close(); }); lightship.registerShutdownHandler(async () => { console.log('Closing Redis connection...'); await redis.quit(); }); lightship.registerShutdownHandler(async () => { console.log('Closing database pool...'); await pool.end(); }); lightship.signalReady(); // Handlers execute in order: HTTP server -> Redis -> Database ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.