Skip to content

feat(api): support timeout_ms on remember and search#40

Open
moltar-bot wants to merge 1 commit into
Keyoku-ai:mainfrom
moltar-bot:feat/request-timeout-remember-search
Open

feat(api): support timeout_ms on remember and search#40
moltar-bot wants to merge 1 commit into
Keyoku-ai:mainfrom
moltar-bot:feat/request-timeout-remember-search

Conversation

@moltar-bot

Copy link
Copy Markdown
Contributor

Summary

  • add optional timeout_ms to POST /api/v1/remember and POST /api/v1/search
  • wrap handler contexts with request-scoped timeouts when provided
  • clamp timeout range to 1s..300s to avoid pathological values

Why

This lets integrations tune extraction/search request budgets explicitly instead of relying only on client abort defaults.

Validation

  • go test ./cmd/keyoku-server/...

@moltar-bot moltar-bot requested a review from tyejcoleman as a code owner April 1, 2026 17:51

@keyoku-bot keyoku-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for wiring timeout_ms through both endpoints — the clamping and request-scoped context are both nice additions.

I'm requesting changes for one behavior issue before we merge: when the request-scoped timeout actually fires, both handlers currently fall through writeInternalErrorWithContext(...), which turns context.DeadlineExceeded into a generic 500 internal server error. Since this PR is explicitly exposing caller-controlled request budgets, timing out on that budget should surface as a timeout/cancelation response (for example 504 with a stable error code), not an internal server failure.

Please add explicit handling for context.DeadlineExceeded / context.Canceled in the remember/search path (or centrally in the error writer), and cover it with a handler test so clients can distinguish budget exhaustion from real server faults.

tyejcoleman added a commit that referenced this pull request Apr 24, 2026
Builds on #40. When a request-scoped timeout (from client-supplied
timeout_ms or an upstream provider deadline) fires, the handler path
previously unwrapped to writeInternalErrorWithContext and surfaced a
generic 500. Since this endpoint now exposes a caller-controlled budget,
budget exhaustion needs a distinct, retryable signal so clients can
separate "my budget was too tight" from "the engine is broken".

- errors.Is(err, context.DeadlineExceeded) -> 504 with
  code=request_timeout, retryable=true. String fallback covers provider
  SDKs that surface "context deadline exceeded" without wrapping.
- errors.Is(err, context.Canceled) -> log and return without writing,
  since the client socket is gone.
- Tests cover both wrapped and string-fallback forms plus the canceled
  no-write case.
tyejcoleman added a commit that referenced this pull request Apr 24, 2026
Builds on #40. When a request-scoped timeout (from client-supplied
timeout_ms or an upstream provider deadline) fires, the handler path
previously unwrapped to writeInternalErrorWithContext and surfaced a
generic 500. Since this endpoint now exposes a caller-controlled budget,
budget exhaustion needs a distinct, retryable signal so clients can
separate "my budget was too tight" from "the engine is broken".

- errors.Is(err, context.DeadlineExceeded) -> 504 with
  code=request_timeout, retryable=true. String fallback covers provider
  SDKs that surface "context deadline exceeded" without wrapping.
- errors.Is(err, context.Canceled) -> log and return without writing,
  since the client socket is gone.
- Tests cover both wrapped and string-fallback forms plus the canceled
  no-write case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants