From 883d267328869d5809a2b48382254ce81649f771 Mon Sep 17 00:00:00 2001 From: beo3000 Date: Fri, 27 Feb 2026 19:48:25 +0100 Subject: [PATCH] db shutdown on deploy --- .gitignore | 7 +------ ka-note/VERSION | 2 +- ka-note/deploy.ps1 | 16 ++++++++++++++++ ka-note/server/ka-note.db-shm | Bin 32768 -> 32768 bytes ka-note/server/ka-note.db-wal | Bin 1746912 -> 2492632 bytes ka-note/server/src/routes/admin.ts | 18 ++++++++++++++++++ 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index d08195b..2a9f1ca 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,5 @@ work/ /import ka-note/server/ka-note.db-wal -ka-note/server/ka-note.db-wal -ka-note/server/ka-note.db-wal ka-note/server/ka-note.db-shm -ka-note/server/ka-note.db-shm -ka-note/server/ka-note.db-wal -ka-note/server/ka-note.db-shm -ka-note/server/ka-note.db-wal + diff --git a/ka-note/VERSION b/ka-note/VERSION index c15c45a..a2ece8c 100644 --- a/ka-note/VERSION +++ b/ka-note/VERSION @@ -1 +1 @@ -1.1.85 \ No newline at end of file +1.1.87 \ No newline at end of file diff --git a/ka-note/deploy.ps1 b/ka-note/deploy.ps1 index bf6316f..244278b 100644 --- a/ka-note/deploy.ps1 +++ b/ka-note/deploy.ps1 @@ -106,6 +106,22 @@ az webapp config appsettings set --name $APP --resource-group $RG --settings ` AZURE_CLIENT_ID=$env:AZURE_CLIENT_ID ` AZURE_TENANT_ID=$env:AZURE_TENANT_ID | Out-Null +Write-Host "=== Graceful DB shutdown ===" -ForegroundColor Cyan +$AppUrl = "https://$APP.azurewebsites.net" +if ($env:KA_NOTE_DEPLOY_API_KEY) { + try { + $shutdownResult = Invoke-RestMethod -Uri "$AppUrl/api/admin/shutdown" -Method POST ` + -Headers @{ Authorization = "Bearer $env:KA_NOTE_DEPLOY_API_KEY" } ` + -UseBasicParsing -TimeoutSec 10 + Write-Host " Shutdown response: $($shutdownResult.message)" -ForegroundColor DarkGray + Start-Sleep -Seconds 3 + } catch { + Write-Host " Shutdown call failed (continuing anyway): $_" -ForegroundColor Yellow + } +} else { + Write-Host " KA_NOTE_DEPLOY_API_KEY not set, skipping graceful shutdown" -ForegroundColor Yellow +} + Write-Host "=== Restart App Service ===" -ForegroundColor Cyan az webapp restart --name $APP --resource-group $RG diff --git a/ka-note/server/ka-note.db-shm b/ka-note/server/ka-note.db-shm index a2ffbaa9cf8c149e3c81b38aa3fb2714f1c07071..9d33ede8c239dca517294f9ef3417b41533acc39 100644 GIT binary patch delta 981 zcmb7?`BP0{7{~ATsap@i^&k;ZDp^9-kSLW@qO@FX6Pl1^8fG+1ru!F|xt;NwG5OI_ z(#^ha2}!n8B$9n!%NFOj?+pis;>M%jo<2pQX5)$xSbq?DjSGG7rZH zvlWg?ms~iklm&;y>_wWzY_XT|-;!48;;MhUI;vgtYLI(csFoZlT#HW_LGh%8xR+|( zk^YwbxPcb@ggcF=@B=}#L^*3Sg^%MY z`ct@a=4K1ufr*02s+@ux;S+d<0W?QB;km+%0F9@m%2~Bc_#~cVAk9@y*b3phAeulK z%E`|YK7|+XqzL8A%olEg3r(a<<>ajtK8=?cM3Kq~T`k-UR|=slfR5TZ)7$aSu$B4WeHw>t^ALc#mNe>kL)s;4s?J zmu9L^(-z?axQ`w*MTOFeg=_EuKD59f`h9KODqMwD^rWfENhuM&gpU|baYp0PKYI%e AI{*Lx delta 546 zcmZo@U}|V!s+V}A%K!rGK+MR%Ag}^RqyTa8UjFK`33@9P@2_Q2Tj=<`<)5%dM`QSO zQq_YE2NEE2|04mYI2(f+P=aCN#O#R+cs4t*$1rY=V7kDv`44B9#byDnD@>DvoP;Jb za?P6j&q-x7BbOf2}F9O6k#5mb03M!Hl4Ha>S zg^FawK}GBmpduNGP!XGCs7P80RKzL`Dw2{86|u;KiX>%$7(f>%_DF6vf zW11XO3=!B=3>Anfg9vOW0|@{NJu?M G?JNMckEEyo diff --git a/ka-note/server/ka-note.db-wal b/ka-note/server/ka-note.db-wal index 6fd2345aeb2942cdcc5ada60dcb45313cf4ea112..d78ed9523c8745470a97620ce9a8a124be6b303a 100644 GIT binary patch delta 3067 zcmZvedpuNIABR!Qm@wl`#7OByZiNz#aVv6ZLN}u6f=)$K?oy`ODVI~EjFimC^$j`5 zD#>+Tg%GOaP?>~6$(uXL*{fOar}vNk{Qkb5wf9=HpLzD?w;kz9N)={d!k7rQ1Y3%U zVqzEpBVyth30sCqV3L>=M#d6{tZ!(wBB8uo0+AfS|>_pQ`f~jUxdyjZg=4LeI38uU|lBxD1<-e8EDIduq z144r7dTW+7p}h4nnpy~^yF}g$va=mb(KMVryp^Cu4DPd?SJX=_V~=$RtB6vCgoF>V zDV@Sr!c;)-6fPzc%`U#Jld(U50meo0IGL@hPFg`cVH|(Z-Y|s)sN=#E3Xvk4a@u`F zy&6yoWbimb9%7%pq3#G+RwO(|O6$btiUzaTHBZQaK#WexBoiBnVcd#iQuR zpYj#Uh^2tSfh~K2(z3C}JFk4BD4x2)COG$U8~*~d8d&B8xt6cIVx|fVcf)p$YZM+{ z*k1#feAvd_n@n;p5&t(}gv0h-S+<$}-mtR!oMm{D5OS$}b^5&yNKA$0lN((l3eCPG z@SF-;-YxB!rvnkMK+OZ#9)9HM#7K8hF1Lo|C}H{M&q;eH!B`h8H@3w}=?rwJ0K@&T zU7RRcr7b#}0I0J++O1}N1yjN`fN>VKLVL<1y;ljj0=lvo9=CHA+A|-zQ9&XXwt5QP zc6VPbECQApYzIOnGd)O@HK3*zww!jO_(kdX^PqSSY`g56i{p~3W5L)v*oMk%zMDER9FUoncyL-L(>ce-7^CjqTV=n^z@vfVvEFW$&B8zqbv z0>Q>Kev+$!$bA=Uoi}tf;yvKU%S@2j&hI5uiPWZ2<=lh$^N8GMN?`|AC(FhF8d$nO zX8T%^WQo#GWhHGxZaX7CpVT~ZU@V(=`Q!LYy~EGt_UA;Zt$km;Y|()06$0skFDR=Mm(P| zkOI_i1Ux2N69VV>Eqp+^23tj43oF)^eTIOpO2i|R>OJIttLg=ymBF^_g8u8k=}+eY z%L2CFJ)UVg`;f!|^95|@bv?dZQO;cgiuc0S=ib4_GOv*lz?p#UvtirL+pk9Z0Y3`1 zyUsA}?p%H72dJV_c+_vuN!yUnRfVwK@jAzMzQwb>+++z}9+^6{ZepbUA)q~mOS4DD zP6Un2O#+rZTzYpSc8qy$Q5`Vfz_ut|i&om|7Xla|aBX~6_KEM}X_|nu0Na%$HaX{L zlQ~Gd4%>`gnf!$E{WIYC3UNI8M}L)&5cMR0n)|Rd4iC<|>XbH7{u?Y!>ee+}&3rTk zXbteTH=BGoshRg(pczCcY|lX{DIzu%J(+niWz8=D5sK6WB<}Htb-M#Q{u`j^6ar<$i7+`*Zv6>REth==@QnebgX9qF0tPJWcCSm%!PY@HtGAfGpHj`VC} zlB;n%pS~aI**vXsP9(OO0t|g1v@dj14C-29O@G0L0CIVXms3zofGX0n#46r4-Q2xb z5afYRQ(nf%ir6E_=e-ZU+psL^4$`xCzhZr<-X0C4=SnG?4pyal3evMKqq6pI;f6%=G}7}T@5Gxzoqs6{Hm3O#T1^D4se@YO-;-_WP|xrnA|G8Yt#5jRptbaQ zIUNO*iqSX4CHhrs{Y4`m1nnC~$%Aqijz$C8Gq|=YK;vd>1Fw^f`}jC$OO(fnfvlW#*v%@GdHkH;Kne<3wj zGn0(8X!^=X&B9kII%oSW^O2gQ|%Bdnk8A4X? z^tQH{$0c8WsF^T7F^*}hxidWXFm&B@K$L2rxO4m#al-_HIY D=*hYH delta 62 zcmV~$w-JH>006)vgMdT{j_4E?zW^N@xPW`mQZfqv=e7se@%ajbBC$j&lPf%wDz&FZ QtJ52dUM91}`hQ=)8?k{E8UO$Q diff --git a/ka-note/server/src/routes/admin.ts b/ka-note/server/src/routes/admin.ts index 885b291..12e5f68 100644 --- a/ka-note/server/src/routes/admin.ts +++ b/ka-note/server/src/routes/admin.ts @@ -3,6 +3,7 @@ import { vacuumPurged } from '../lib/sync-service.js'; import { checkIntegrity } from '../lib/backup-service.js'; import { handle } from '../lib/route-utils.js'; import type { AuthEnv } from '../middleware/auth.js'; +import { sqlite } from '../db/connection.js'; const admin = new Hono(); @@ -18,4 +19,21 @@ admin.get('/integrity', handle('admin/integrity', async (c) => { return c.json(result, result.ok ? 200 : 500); })); +// Graceful shutdown: checkpoint WAL, close DB, exit. +// Call from deploy pipeline before restarting the container. +admin.post('/shutdown', handle('admin/shutdown', async (c) => { + console.log('[admin] shutdown requested via API'); + setTimeout(() => { + try { + sqlite.pragma('wal_checkpoint(TRUNCATE)'); + sqlite.close(); + console.log('[admin] database closed cleanly, exiting'); + } catch (e) { + console.error('[admin] error during shutdown:', e); + } + process.exit(0); + }, 100); + return c.json({ ok: true, message: 'shutting down' }); +})); + export default admin;