My PaaS for hosting multiple elasticsearch clusters in a Kubernetes environment.
pagedb docs notes unsorted docs-endpoints-implementation-plan.md
2.8 kB
Markdown
at main

Docs Endpoints Implementation Plan #

Endpoints #

Endpoint Method Path Status Response
IndexDoc POST /v1/search/{instanceId}/docs 201 DocumentIndexResponse
SearchDocs GET /v1/search/{instanceId}/docs 200 []Document
DeleteDoc DELETE /v1/search/{instanceId}/docs/{docId} 204 —

Shared Helpers (add to server.go) #

defaultIndex(idx *string) string #

Returns "default" if idx is nil/empty, otherwise the dereferenced value.

readESBody(resp *esapi.Response) ([]byte, error) #

Reads and closes the ES response body, returns bytes. Prevents body leaks.

validateInstanceOwner(ctx context.Context, instanceId string, username string) error #

Fetches the ES cluster from K8s, checks:

  • Instance exists → 404 if not
  • paas-instance-owner label matches username → 404 if not (consistent with existing pattern)

Returns error with appropriate message; callers map to HTTP status.

Endpoint Implementations #

IndexDoc #

  1. Parse body → DocumentCreateRequest (via reqBody[T])
  2. validateInstanceOwner → 404 if not owner/missing
  3. getESClient → 500 if fails (instance not ready)
  4. Resolve index via defaultIndex(req.Index)
  5. Build JSON body: {"text": req.Text}
  6. Call esClient.Index(index, body, nil, ptr("wait_for")) — auto-generate doc ID, refresh=wait_for for immediate searchability
  7. Parse ES response JSON → extract _id and _index
  8. Return 201 + DocumentIndexResponse{DocumentId, Index}

SearchDocs #

  1. validateInstanceOwner → 404
  2. getESClient → 500
  3. Resolve index via defaultIndex(params.Index)
  4. Build ES query: {"query": {"match": {"text": params.Q}}}
  5. Call esClient.Search(index, body)
  6. Parse hits → []api.Document:
    • _id → DocumentId
    • _source.text → Text
    • _index → Index
    • _score → Score (pointer, omit if zero)
  7. Return 200 + document array

DeleteDoc #

  1. validateInstanceOwner → 404
  2. getESClient → 500
  3. Call esClient.Delete(params.Index, docId)
  4. Check ES response status: if 404 → return 404 "document not found"
  5. Return 204 No Content

Design Decisions #

Decision Choice Rationale
Index default "default" Matches OpenAPI spec default
Index mapping ES dynamic mapping Simplest — ES auto-creates index and maps text field
IndexDoc refresh wait_for Document immediately searchable after indexing
SearchDocs query match on text field Simple full-text search, sufficient for MVP
Ownership check paas-instance-owner label Returns 404 for both not-found and not-owned (consistent with existing pattern)
Auth requirement Owner-only User must own the ES instance to operate on its docs