@spfn/core 0.2.0-beta.16 → 0.2.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/server.md CHANGED
@@ -191,16 +191,79 @@ const api = createApi<AppRouter>();
191
191
 
192
192
  ## Graceful Shutdown
193
193
 
194
- Automatic graceful shutdown handling:
194
+ Automatic graceful shutdown with drain behavior (AWS drain style):
195
195
 
196
- 1. Stop accepting new connections
197
- 2. Wait for in-flight requests
198
- 3. Close database connections
199
- 4. Close Redis connections
200
- 5. Exit process
196
+ ```
197
+ SIGTERM
198
+
199
+ ├─ Phase 1: server.close() ← 연결 거부, 진행 중 요청 대기
200
+ ├─ Phase 2: stopBoss() ← pg-boss 작업 정리
201
+ ├─ Phase 3: ShutdownManager.execute()
202
+ │ ├─ drain: tracked operations 완료 대기
203
+ │ └─ hooks: 등록된 훅 순서대로 실행
204
+ ├─ Phase 4: beforeShutdown lifecycle ← 기존 lifecycle 호환
205
+ ├─ Phase 5: closeDatabase / closeCache
206
+ └─ process.exit(0)
207
+ ```
201
208
 
202
209
  **Signals handled:** `SIGTERM`, `SIGINT`
203
210
 
211
+ ### ShutdownManager
212
+
213
+ 모듈별 독립적인 shutdown 훅 등록과 장기 작업 추적:
214
+
215
+ ```typescript
216
+ import { getShutdownManager } from '@spfn/core/server';
217
+
218
+ const shutdown = getShutdownManager();
219
+
220
+ // 1. Shutdown 훅 등록 — 모듈별 독립 cleanup
221
+ shutdown.onShutdown('ai-client', async () =>
222
+ {
223
+ await openaiClient.close();
224
+ }, { timeout: 5000, order: 10 });
225
+
226
+ shutdown.onShutdown('search-index', async () =>
227
+ {
228
+ await elasticClient.close();
229
+ }, { order: 20 });
230
+
231
+ // 2. 장기 작업 추적 — shutdown 시 완료까지 대기
232
+ const result = await shutdown.trackOperation(
233
+ 'ai-generate',
234
+ aiService.generate(prompt)
235
+ );
236
+ // shutdown 중이면 자동으로 throw → 503
237
+
238
+ // 3. Shutdown 상태 확인
239
+ if (shutdown.isShuttingDown())
240
+ {
241
+ return c.json({ error: 'Server is shutting down' }, 503);
242
+ }
243
+ ```
244
+
245
+ ### Timeout Configuration
246
+
247
+ ```typescript
248
+ defineServerConfig()
249
+ .shutdown({
250
+ timeout: 280000, // 280s (default: k8s 300s - 5s preStop - 15s margin)
251
+ })
252
+ .build();
253
+ ```
254
+
255
+ AI 파이프라인 등 장기 작업이 있는 앱은 Helm chart과 함께 조정:
256
+
257
+ ```yaml
258
+ # apps/values.yaml
259
+ gracefulShutdown:
260
+ terminationGracePeriodSeconds: 660 # 11분
261
+ ```
262
+
263
+ ```bash
264
+ SHUTDOWN_TIMEOUT=640000 # 660 - 5 - 15 = 640s
265
+ ```
266
+
204
267
  ---
205
268
 
206
269
  ## Health Check
@@ -208,8 +271,12 @@ Automatic graceful shutdown handling:
208
271
  Built-in health endpoint at `/health`:
209
272
 
210
273
  ```bash
274
+ # Normal
211
275
  curl http://localhost:8790/health
212
276
  # { "status": "ok", "timestamp": "2024-..." }
277
+
278
+ # During shutdown → 503
279
+ # { "status": "shutting_down", "timestamp": "2024-..." }
213
280
  ```
214
281
 
215
282
  ---
@@ -229,6 +296,9 @@ DATABASE_READ_URL=postgresql://replica:5432/mydb
229
296
 
230
297
  # Redis
231
298
  REDIS_URL=redis://localhost:6379
299
+
300
+ # Shutdown
301
+ SHUTDOWN_TIMEOUT=280000 # Milliseconds (default: 280s)
232
302
  ```
233
303
 
234
304
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spfn/core",
3
- "version": "0.2.0-beta.16",
3
+ "version": "0.2.0-beta.18",
4
4
  "description": "SPFN Framework Core - File-based routing, transactions, repository pattern",
5
5
  "type": "module",
6
6
  "exports": {