Skip to content

Implement own Service Manager client for separate-bucket multitenancy #810

@Schmarvinius

Description

@Schmarvinius

Context

For separate-bucket multitenancy, the OSS module currently relies on the @cap-js/attachments MTX sidecar plugin to handle tenant onboarding/offboarding (creating/deleting per-tenant object store instances and bindings via the Service Manager API). The Java app only has a read-only SM client for runtime credential resolution (getBinding()).

This works but couples us to the JS plugin for a critical lifecycle operation, and we lose control over:

  • Bucket content cleanup on unsubscribe (JS sidecar only deletes the SM instance/binding, doesn't empty the bucket first)
  • Cache warming on subscribe (first request after provisioning hits a cold cache)
  • Error resilience (orphaned instance cleanup on binding failure, resilient unsubscribe that continues after partial failures)

Goal

Implement a full Service Manager client in the Java OSS module that handles the complete tenant lifecycle independently, without requiring @cap-js/attachments in the MTX sidecar.

Scope

SM Client (write operations)

  • createInstance(tenantId, planId) — create object store instance with polling for async completion
  • createBinding(tenantId, instanceId) — create service binding
  • deleteBinding(bindingId) — delete service binding
  • deleteInstance(instanceId) — delete instance with async polling
  • getOfferingId() / getPlanId(offeringId) — discover objectstore offering and plan (standard / s3-standard)

Lifecycle Orchestration

  • Subscribe handler (DeploymentService.EVENT_SUBSCRIBE): idempotency check → create instance → create binding → warm client cache. Clean up orphaned instance if binding fails.
  • Unsubscribe handler (DeploymentService.EVENT_UNSUBSCRIBE): delete bucket contents → evict cache → delete binding → delete instance. Errors logged but don't block flow.

Token Provider

  • OAuth2 client credentials flow + mTLS support
  • In-memory token caching with refresh margin

Registration

  • Wire SM client, lifecycle handler, and subscribe/unsubscribe event handlers in Registration.registerSeparateMode()
  • Service Manager binding discovery from CdsEnvironment

Notes

  • The existing read-only getBinding() in ServiceManagerClient can be extended rather than rewritten
  • Both standard and s3-standard plans should be supported (try standard first, fall back to s3-standard)
  • Labels: tenant_id: [tenantId], service: ["OBJECT_STORE"]
  • Reference implementation: cap-js/attachments lib/mtx/server.js

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions