Przejdź do treści
Biblioteka skilli
Programowanie · Budowanie i kod

nodejs-graceful-shutdown

/nodejs-graceful-shutdown

Wdraża lub naprawia łagodne zamykanie usługi Node.js: sygnały SIGTERM i SIGINT, dokańczanie połączeń i sygnał health-check.

Repozytorium
dalcom-skills ↗
Licencja
Apache-2.0
Ostatnia zmiana repozytorium
10.11.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
2
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 10.11.2026, bez odwołań do wycofanych modeli i API.

Licencja

Apache-2.0, otwarta: można używać i zmieniać, z zachowaniem licencji i informacji o zmianach.

Co robi i kiedy

Wdraża lub naprawia łagodne zamykanie usługi Node.js: sygnały SIGTERM i SIGINT, dokańczanie połączeń i sygnał health-check.

Oryginalny opis (EN)

Use when asked to implement or fix service termination: SIGTERM or SIGINT, connection draining, health-check signaling. Not for general service scaffolding: use nodejs-service-foundations.

Jak działa

  1. Wire one handler for both signals
  2. Fail health first so the balancer looks away
  3. Drain connections, then close what you opened
  4. Prove it with a companion test
  5. When draining fails
  6. What you hand back
Sekcje z nagłówków SKILL.md, w oryginale · 60 linii, 770 słów
Podgląd SKILL.md
---
name: nodejs-graceful-shutdown
description: 'Use when asked to implement or fix service termination: SIGTERM or SIGINT, connection draining, health-check signaling. Not for general service scaffolding: use nodejs-service-foundations.'
---

# Node.js graceful shutdown

You make a Node.js server stop without dropping work. When the process gets SIGTERM or SIGINT (a deploy, a scaler, a Ctrl-C), it stops accepting new connections, tells the load balancer it is going away, lets in-flight requests finish inside a deadline, closes its database and queue handles, and exits with a code that says whether the drain was clean. If the ask is really about scaffolding the whole service (env, logging, errors), that belongs to nodejs-service-foundations instead.

This stays local and reversible: you edit only the server shutdown handler and add one companion test, both rolled back through version control. You never touch remote state. The only runtime side effect is starting a short-lived server to watch it drain.

What you need before starting:

- `SOURCES`: files under `$CWD/src` or `$CWD/lib` holding the `http.createServer` or Express/Fastify `listen` bootstrap (one file is fine). Required.
- `SERVER_PORT`: TCP port the test server binds. Required.
- `HEALTH_ROUTE`: health or readiness path. Required.
- `DRAIN_TIMEOUT_MS`: milliseconds to wait for in-flight requests before forcing the exit. Required, positive integer, default `10000`.
- `EXTERNAL_DEPENDENCIES`: every external handle the app opens (database pools, Redis clients, queue producers). Required, may be empty.

## Wire one handler for both signals

Read every file in `SOURCES` and find the bootstrap: the `listen` call and the variable holding the server instance. Keep any existing named `process.on` handler and update it rather than registering a second handler on the same signal. Both `SIGTERM` and `SIGINT` must end at a single `shutdown` function, guarded by module-scope state declared as `let isShuttingDown = false`. If that flag does not exist yet, add it.

## Fail health first so the balancer looks away

The first thing `shutdown` does is set `isShuttingDown = true`, and the health endpoint reads that flag on every request: `200 OK` with `{"status":"ok"}` while serving, `503 Service Unavailable` with `{"status":"shutting_down"}` once draining starts. This flip must land before `server.close()` runs, so a health probe sent right after the signal reliably sees the 503 while the server is still up.

## Drain connections, then close what you opened

After the health flip, call `server.close()` on the real server instance and await it (never a fixed sleep), raced against a `DRAIN_TIMEOUT_MS` timeout. If close resolves first the drain was graceful; if the timer wins, requests are still in flight and the exit must be non-zero. Then close every entry in `EXTERNAL_DEPENDENCIES`:

- database pools with `pool.end()`
- Redis clients with `redis.quit()`
- queue producers with `producer.disconnect()`

Leave OS-level sockets alone. Await every close; an unresponsive dependency gets recorded, not retried forever. Partial cleanup (some handles closed, others not) counts as failure.

Exit `0` only when the server drained inside the deadline and every dependency closed. Exit `1` when the drain timed out or any dependency stayed unresponsive, so callers can tell a clean drain from a forced one.

## Prove it with a companion test

Write `<filename>.test.ts` next to the handler and run it with `node --test` or the project's runner until it is green. The test spawns the server with `DRAIN_TIMEOUT_MS=500`, then:

- requests `GET /<HEALTH_ROUTE>` and expects `200`
- sends `SIGTERM`
- immediately requests health again and expects `503` with `shutting_down`
- holds a long-running request across the signal and expects it to complete before exit
- waits for the process to exit and expects code `0` when the long request finished inside the deadline
- reruns a scenario where the long request outlasts the deadline and expects a non-zero exit

All of those assertions must exist and pass.

## When draining fails

- Unresponsive dependency hangs `closeExternalConnections()`: record which one, give each dependency close its own timeout, and exit `1`. The companion test sees the non-zero code.
- Active requests outliving `DRAIN_TIMEOUT_MS`: the timeout wins the race against `server.close()`. Exit `1`, and either raise the timeout or stop the service holding connections past it.
- Partial cleanup: some handles closed, others not. Exit `1`. The usual cause is a handle missing from `EXTERNAL_DEPENDENCIES`, so add it.
- Flag checked too late: a request that started async work before the signal can still fire a database query after the flag is set. Put the `isShuttingDown` guard before the I/O call, not after.
- Health route ignoring the flag: the balancer keeps sending traffic to a draining pod. The 503 must come immediately after the signal and before `server.close()`.

## What you hand back

Edited shutdown code plus a passing companion test, demonstrating the 503 health flip ahead of `server.close()`, a clean drain inside the deadline, and an exit code that separates graceful shutdown from deadline-forced termination.
Pliki w paczce (2)
  • SKILL.md 5 KB
  • agents/openai.yaml 1 KB

Wersje

RepozytoriumWynikLicencja
Ta strona · gosuda/dalcom-skills100Apache-2.0
OutlineDriven/outline-driven-development100Apache-2.0

Migawka bazy z 13.11.2026 · wersja paczki 7d7e663ecc22 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100nodejs-service-foundations
    Ustawia lub utwardza podstawy usługi Node.js: walidację zmiennych środowiskowych, logowanie, typowane błędy i podpinanie wyłączania.
  • 90nodejs-service-foundations
    Ustawia lub utwardza fundamenty usługi Node.js: walidację env, logowanie, typowane błędy, type stripping i obsługę zamykania.
  • 100nodejs
    Pomaga budować i prowadzić zwykły backend Node.js z Express 5: układ projektu, poprawność async, centralny middleware błędów, konfiguracja z szybkim zatrzymaniem i łagodne zamykanie na SIGTERM.
  • 100spine-service
    Buduje od zera nową usługę gotową do produkcji: zarządzanie konfiguracją, health checki, łagodne zamykanie i logowanie strukturalne.
  • 100graceful-shutdown-draining-in-flight-ticks
    Prowadzi ponowne wdrożenie lub restart workerów ticków pod SIGTERM tak, by nie zgubić wpisów w kolejce, zapisów do sinków ani offsetów konsumentów; osobno wymaga decyzji o otwartych zleceniach.
  • 90reviewing-go-services
    Ocenia usługę w Go pod kątem ryzyk produkcyjnych, np. brakujących limitów czasu HTTP, zamknięcia przy SIGTERM i pul połączeń.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.