)]}'
{
  "commit": "c13f1e074207ddb450fd697153a79a571358b3f4",
  "tree": "fadf920337efd33193a8d67f8cabe6bbc16d81af",
  "parents": [
    "099507392f937d99a4f648079d2e89d9e8a43c7a"
  ],
  "author": {
    "name": "ZIHAN DAI",
    "email": "99155080+PDGGK@users.noreply.github.com",
    "time": "Fri Jul 24 13:22:17 2026 +1000"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Fri Jul 24 11:22:17 2026 +0800"
  },
  "message": "Fix session pool lifecycle bugs in getSession/releaseSession/cleanupIdleSessions (#19)\n\nSeveral related lifecycle bugs in BaseSessionPool where session bookkeeping\n(pool / idleSessions / activeSessions / waitQueue) was updated inconsistently\nacross await points:\n\n- A timed-out getSession() waiter was never removed from the wait queue: the\n  timeout matched indexOf(resolve), but the queue holds a wrapper closure, so\n  the match always failed. releaseSession() later shifted that dead waiter,\n  marked the session active, and resolved an already-rejected promise, leaking\n  the session and eventually starving the pool.\n- The create-new-session branch reclaimed the freshly created session with a\n  blind idleSessions.shift() (front), but createSession() pushes to the back;\n  under interleaving (a session released into idle during the await) it evicted\n  a different session and left the new one tracked as both idle and active.\n- The idle-reuse branch added the session to activeSessions but never set\n  inUse\u003dtrue (the new-session and waiter branches both do), so\n  syncDatabaseContextToPool treated an actively-in-use session as idle and could\n  issue USE on it concurrently with the caller\u0027s in-flight request.\n- cleanupIdleSessions() checked pool.length \u003e minSize against the constant\n  pre-cleanup size, so it could queue every idle session and shrink the pool\n  below minPoolSize.\n- cleanupIdleSessions() awaited session.close() before removing the session from\n  pool/idle; since isOpen() stays true until the close RPC resolves, a\n  concurrent getSession() could hand out a session that was being destroyed.\n\nFix each (named/settled-guarded waiter with correct removal + release loop;\ntargeted idle removal; inUse on reuse; projected-size cleanup guard;\nsplice-before-close) and add deterministic regression tests.\n\nSigned-off-by: Zihan Dai \u003c99155080+PDGGK@users.noreply.github.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "8580daffc24c2a59dcd98ca81c351ae761acd968",
      "old_mode": 33188,
      "old_path": "src/client/BaseSessionPool.ts",
      "new_id": "cfd0ff0e271fc27c83cc31abbbebf186b919a54c",
      "new_mode": 33188,
      "new_path": "src/client/BaseSessionPool.ts"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "64bf2e63b0e249c157f67d23ded25870d0239318",
      "new_mode": 33188,
      "new_path": "tests/unit/BaseSessionPoolLifecycle.test.ts"
    }
  ]
}
