[Claude code generated PR] refactor(historian-base): extract createRouteContext helper#26606
Conversation
…aily-repo-status.md-4130 Add agentic workflow daily-repo-status
…ode-simplifier.md-1519 Add agentic workflow code-simplifier
…uplicate-code-detector.md-4767 Add agentic workflow duplicate-code-detector
…to vermadhr/ghawWorkflowsForSimplification
…ication Vermadhr/ghaw workflows for simplification
Eliminates the duplicated 4-line router/throttle prologue repeated across 8 Historian route modules by extracting it into a single createRouteContext() helper in routes/utils.ts. summaries.ts uses a destructuring alias to preserve its existing local variable name. Closes microsoft#26591 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR extracts a repeated 4-line router/throttle setup block shared across 8 Historian route modules into a single createRouteContext() helper, reducing duplication and centralizing the configuration in routes/utils.ts.
Changes:
- Added
createRouteContext()helper andIHistorianRouteContextinterface toroutes/utils.ts - Refactored 8 route files (
blobs.ts,commits.ts,refs.ts,tags.ts,trees.ts,contents.ts,headers.ts,summaries.ts) to use the new helper - Added 6 unit tests for
createRouteContextinroutes.spec.ts
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
routes/utils.ts |
Adds IHistorianRouteContext interface and createRouteContext() helper; also includes minor formatting fixes |
routes/git/blobs.ts |
Adopts createRouteContext(); removes duplicate prologue and unused imports |
routes/git/commits.ts |
Adopts createRouteContext(); removes duplicate prologue and unused imports |
routes/git/refs.ts |
Adopts createRouteContext(); removes duplicate prologue and unused imports |
routes/git/tags.ts |
Adopts createRouteContext(); removes duplicate prologue and unused imports |
routes/git/trees.ts |
Adopts createRouteContext(); removes duplicate prologue and unused imports |
routes/repository/contents.ts |
Adopts createRouteContext(); removes duplicate prologue and unused imports |
routes/repository/headers.ts |
Adopts createRouteContext(); removes duplicate prologue and unused imports |
routes/summaries.ts |
Adopts createRouteContext() with destructuring alias for tenantGeneralThrottleOptions |
services/restGitService.ts |
Indentation-only formatting fix |
runnerFactory.ts |
Indentation-only formatting fixes |
test/routes.spec.ts |
Adds 6 unit tests for createRouteContext() |
| assert.strictEqual( | ||
| typeof ctx.tenantThrottleOptions.throttleIdPrefix === "function" | ||
| ? ctx.tenantThrottleOptions.throttleIdPrefix(mockReq) | ||
| : undefined, | ||
| "myTenant", | ||
| ); |
There was a problem hiding this comment.
The defensive ternary used for throttleIdPrefix means that if throttleIdPrefix is accidentally set to a non-function value, this test will pass with undefined === "myTenant" rather than failing. The test should directly assert that throttleIdPrefix is a function first (e.g., assert.strictEqual(typeof ctx.tenantThrottleOptions.throttleIdPrefix, "function")), and then call it unconditionally. This would produce a clear failure message if the shape changes.
| assert.strictEqual( | |
| typeof ctx.tenantThrottleOptions.throttleIdPrefix === "function" | |
| ? ctx.tenantThrottleOptions.throttleIdPrefix(mockReq) | |
| : undefined, | |
| "myTenant", | |
| ); | |
| assert.strictEqual(typeof ctx.tenantThrottleOptions.throttleIdPrefix, "function"); | |
| assert.strictEqual(ctx.tenantThrottleOptions.throttleIdPrefix(mockReq), "myTenant"); |
| restTenantThrottlers: Map<string, IThrottler>, | ||
| ): IHistorianRouteContext { | ||
| const router: Router = Router(); | ||
| const maxTokenLifetimeSec = (config.get("maxTokenLifetimeSec") as number | null) ?? 0; |
There was a problem hiding this comment.
The previous code in the individual route files used config.get("maxTokenLifetimeSec") without a fallback, while this helper now silently falls back to 0 when the key is absent. A value of 0 for maxTokenLifetimeSec causes all tokens to be immediately rejected in verifyToken, which is a silent behavioral change for any deployment where this config key is accidentally omitted. The PR description acknowledges this and notes a startup warning could be added as a follow-up, but returning 0 without any warning logged here makes the failure mode hard to diagnose. Consider at least logging a warning (e.g., via Lumberjack.warning) when config.get("maxTokenLifetimeSec") returns null/undefined before falling back to 0.
| const maxTokenLifetimeSec = (config.get("maxTokenLifetimeSec") as number | null) ?? 0; | |
| const rawMaxTokenLifetimeSec = config.get("maxTokenLifetimeSec") as number | null | undefined; | |
| if (rawMaxTokenLifetimeSec == null) { | |
| Lumberjack.warning( | |
| "Configuration key 'maxTokenLifetimeSec' is missing; defaulting to 0 which will cause all tokens to be immediately rejected.", | |
| getLumberBaseProperties(), | |
| ); | |
| } | |
| const maxTokenLifetimeSec = (rawMaxTokenLifetimeSec as number | null) ?? 0; |
zhangxin511
left a comment
There was a problem hiding this comment.
Looks good, lease hace @znewton for another eye
…to dhr-verma/extractHistorianRouteContext
…Sec is unconfigured The createRouteContext() refactoring in #26606 added a ?? 0 fallback for maxTokenLifetimeSec when the config key is absent. This changed the value from undefined (comparison always passes) to 0 (comparison always fails), causing every token to be rejected with "Invalid token expiry" in Docker e2e test runs. Fix: allow maxTokenLifetimeSec to be undefined and skip the expiry range check when it is not configured, matching the pre-refactor behavior. Fixes AB#62821 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nfigured (#26859) ## Summary The `createRouteContext()` refactoring in #26606 (merged March 3) added a `?? 0` null-coalescing fallback for `maxTokenLifetimeSec`. When the config key is absent (as in the Docker Historian config), this changed the value from `undefined` to `0`, causing the expiry range check to reject **every** token: ```typescript // Before: undefined — (exp - iat > undefined) is always false → tokens pass // After: 0 — (exp - iat > 0) is always true → all tokens rejected ``` This broke all Docker e2e test runs since March 3, causing ~1,700 auto-filed flaky test issues. ### Changes - Allow `maxTokenLifetimeSec` to be `undefined` in `IHistorianRouteContext` and `verifyToken()` - Skip the expiry range check when `maxTokenLifetimeSec` is not configured - Update test to assert `undefined` instead of `0` when config key is absent Fixes [AB#62821](https://dev.azure.com/fluidframework/235294da-091d-4c29-84fc-cdfc3d90890b/_workitems/edit/62821) ## Test plan - [x] CI passes (historian build + server pipelines) - [x] Docker e2e tests should stop failing with "Invalid token expiry" - [x] Existing `createRouteContext` tests updated and passing 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nfigured (microsoft#26859) ## Summary The `createRouteContext()` refactoring in microsoft#26606 (merged March 3) added a `?? 0` null-coalescing fallback for `maxTokenLifetimeSec`. When the config key is absent (as in the Docker Historian config), this changed the value from `undefined` to `0`, causing the expiry range check to reject **every** token: ```typescript // Before: undefined — (exp - iat > undefined) is always false → tokens pass // After: 0 — (exp - iat > 0) is always true → all tokens rejected ``` This broke all Docker e2e test runs since March 3, causing ~1,700 auto-filed flaky test issues. ### Changes - Allow `maxTokenLifetimeSec` to be `undefined` in `IHistorianRouteContext` and `verifyToken()` - Skip the expiry range check when `maxTokenLifetimeSec` is not configured - Update test to assert `undefined` instead of `0` when config key is absent Fixes [AB#62821](https://dev.azure.com/fluidframework/235294da-091d-4c29-84fc-cdfc3d90890b/_workitems/edit/62821) ## Test plan - [x] CI passes (historian build + server pipelines) - [x] Docker e2e tests should stop failing with "Invalid token expiry" - [x] Existing `createRouteContext` tests updated and passing 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nfigured (microsoft#26859) ## Summary The `createRouteContext()` refactoring in microsoft#26606 (merged March 3) added a `?? 0` null-coalescing fallback for `maxTokenLifetimeSec`. When the config key is absent (as in the Docker Historian config), this changed the value from `undefined` to `0`, causing the expiry range check to reject **every** token: ```typescript // Before: undefined — (exp - iat > undefined) is always false → tokens pass // After: 0 — (exp - iat > 0) is always true → all tokens rejected ``` This broke all Docker e2e test runs since March 3, causing ~1,700 auto-filed flaky test issues. ### Changes - Allow `maxTokenLifetimeSec` to be `undefined` in `IHistorianRouteContext` and `verifyToken()` - Skip the expiry range check when `maxTokenLifetimeSec` is not configured - Update test to assert `undefined` instead of `0` when config key is absent Fixes [AB#62821](https://dev.azure.com/fluidframework/235294da-091d-4c29-84fc-cdfc3d90890b/_workitems/edit/62821) ## Test plan - [x] CI passes (historian build + server pipelines) - [x] Docker e2e tests should stop failing with "Invalid token expiry" - [x] Existing `createRouteContext` tests updated and passing 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
createRouteContext()helper inroutes/utils.tsIHistorianRouteContextinterface for the returned context objectsummaries.tsuses a destructuring alias (tenantThrottleOptions: tenantGeneralThrottleOptions) to preserve its existing local variable name without touching downstream codeRouter,IThrottleMiddlewareOptions, andConstantsimports from the 8 standard route filesTest plan
pnpm run build:compilepasses (root)npm run testpasses inhistorian-base— 51 tests passing (6 new unit tests forcreateRouteContext)maxTokenLifetimeSecvalue, throttle options shape, throttler map wiring, absent-key fallback to0Related
Closes #26591
Review notes
maxTokenLifetimeSecis absent from config, the helper falls back to0. InverifyTokenthis causes all tokens to be rejected (safe-fail). A startup warning could be added in a follow-up if desired.throttleIdPrefixtest uses a defensive ternary; a future cleanup could split it into an explicit type assertion + direct call for clearer failure messages.🤖 Generated with Claude Code