Class: Pikuri::VectorDb::Server::Chroma

Inherits:
Object
  • Object
show all
Defined in:
lib/pikuri/vector_db/server/chroma.rb

Overview

Supervisor for a self-managed Chroma docker container. Pairs with Backend::Chroma: this class owns the process; Backend::Chroma owns the HTTP client that talks to it. #client returns a Backend::Chroma pre-pointed at the running container.

Why split server from client

Container lifecycle and HTTP wire protocol have nothing in common — they’re separate jobs reading separate man pages. Splitting them keeps Backend::Chroma a thin Faraday client (the audit-friendly shape) and concentrates the docker-shaped complexity in one place a reader can skip when they don’t care.

Hosts that already manage Chroma elsewhere (a production deployment, a docker-compose stack, a Kubernetes service) wire port:) directly and never touch this class.

The lifecycle lives in DockerContainer

This class carries Chroma’s identity — image pin, container name, persist path, heartbeat path — and hands it to a composed DockerContainer, which does the docker work and documents the shared rationale: the pikuri-internal-* namespace squat, ephemeral-container-persistent-data, the subprocess seam, the 127.0.0.1 binding, loud boot errors vs quiet teardown. What stays here besides identity: the #default_data_dir resolution, the Backend::Chroma factory, and the Finalizers registration (the supervisor is the host-facing ownership boundary, so it — not the helper —is what registers and what a host unregisters).

Constant Summary collapse

IMAGE =

Returns pinned chroma docker image. Bumping this constant is how the codebase upgrades the chroma version: #ensure_running! recreates the container from scratch on the next boot, so it comes up on the new pin automatically (the bind-mounted corpus is untouched).

Returns:

  • (String)

    pinned chroma docker image. Bumping this constant is how the codebase upgrades the chroma version: #ensure_running! recreates the container from scratch on the next boot, so it comes up on the new pin automatically (the bind-mounted corpus is untouched).

'chromadb/chroma:1.5.9'
CONTAINER_NAME =

Returns the container name pikuri claims for its chroma supervisor. Prefix “pikuri-internal-” is the namespace pikuri squats — see DockerContainer.

Returns:

  • (String)

    the container name pikuri claims for its chroma supervisor. Prefix “pikuri-internal-” is the namespace pikuri squats — see DockerContainer.

'pikuri-internal-chroma'
LABEL =

Returns docker label set on every container this class creates. Used by future docker ps –filter “label=#{LABEL}” enumeration; not load-bearing for the #ensure_running! algorithm itself.

Returns:

  • (String)

    docker label set on every container this class creates. Used by future docker ps –filter “label=#{LABEL}” enumeration; not load-bearing for the #ensure_running! algorithm itself.

'pikuri.internal=true'
CONTAINER_PERSIST_DIR =

Returns path inside the container where chroma persists its data. Chroma 1.x (the pinned IMAGE line) stores its SQLite + segment files at /data — this is the -v target the host’s #default_data_dir bind-mounts onto. (Chroma 0.x used /chroma/chroma; mounting that path against a 1.x image silently leaves the host dir empty while the data accumulates in the container’s writable layer, where teardown would destroy it.).

Returns:

  • (String)

    path inside the container where chroma persists its data. Chroma 1.x (the pinned IMAGE line) stores its SQLite + segment files at /data — this is the -v target the host’s #default_data_dir bind-mounts onto. (Chroma 0.x used /chroma/chroma; mounting that path against a 1.x image silently leaves the host dir empty while the data accumulates in the container’s writable layer, where teardown would destroy it.)

'/data'
DEFAULT_HEALTHCHECK_TIMEOUT =

Returns default seconds to wait for the container’s HTTP heartbeat to start returning 200 after docker run.

Returns:

  • (Integer)

    default seconds to wait for the container’s HTTP heartbeat to start returning 200 after docker run.

30

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data_dir: nil, port: 8000, healthcheck_timeout: DEFAULT_HEALTHCHECK_TIMEOUT, connection: nil) ⇒ Server::Chroma

Parameters:

  • data_dir (String, Pathname, nil) (defaults to: nil)

    host path to bind-mount as chroma’s persist dir. nil resolves to #default_data_dir.

  • port (Integer) (defaults to: 8000)

    host port to publish.

  • healthcheck_timeout (Integer) (defaults to: DEFAULT_HEALTHCHECK_TIMEOUT)
  • connection (Faraday::Connection, nil) (defaults to: nil)

    DI hook for tests. Production callers leave it nil.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/pikuri/vector_db/server/chroma.rb', line 105

def initialize(data_dir: nil, port: 8000,
               healthcheck_timeout: DEFAULT_HEALTHCHECK_TIMEOUT,
               connection: nil)
  @data_dir = Pathname.new(data_dir || default_data_dir).expand_path
  @port = port
  @container = DockerContainer.new(
    name: CONTAINER_NAME, image: IMAGE, label: LABEL,
    host_port: port, container_port: 8000,
    volume: "#{@data_dir}:#{CONTAINER_PERSIST_DIR}",
    health_path: '/api/v2/heartbeat',
    healthcheck_timeout: healthcheck_timeout,
    connection: connection
  )
  @finalizer_handle = nil
end

Instance Attribute Details

#data_dirPathname (readonly)

Returns host-side data directory.

Returns:

  • (Pathname)

    host-side data directory.



122
123
124
# File 'lib/pikuri/vector_db/server/chroma.rb', line 122

def data_dir
  @data_dir
end

#portInteger (readonly)

Returns host-side port.

Returns:

  • (Integer)

    host-side port.



125
126
127
# File 'lib/pikuri/vector_db/server/chroma.rb', line 125

def port
  @port
end

Class Method Details

.ensure_running(data_dir: nil, port: 8000, healthcheck_timeout: DEFAULT_HEALTHCHECK_TIMEOUT) ⇒ Server::Chroma

Construct a server and immediately ensure it’s running. Convenience factory — equivalent to new(…).tap(&:ensure_running!).

Parameters:

  • data_dir (String, Pathname, nil) (defaults to: nil)

    host path bind-mounted into the container’s persist directory. nil resolves to #default_data_dir ($XDG_CACHE_HOME or ~/.cache, then pikuri/chroma). Created if missing.

  • port (Integer) (defaults to: 8000)

    host port bound to chroma’s 8000. Bound to 127.0.0.1 only.

  • healthcheck_timeout (Integer) (defaults to: DEFAULT_HEALTHCHECK_TIMEOUT)

    seconds to poll /api/v2/heartbeat before giving up.

Returns:



89
90
91
92
93
94
95
# File 'lib/pikuri/vector_db/server/chroma.rb', line 89

def self.ensure_running(data_dir: nil, port: 8000,
                        healthcheck_timeout: DEFAULT_HEALTHCHECK_TIMEOUT)
  new(
    data_dir: data_dir, port: port,
    healthcheck_timeout: healthcheck_timeout
  ).tap(&:ensure_running!)
end

Instance Method Details

#client(collection:) ⇒ Backend::Chroma

Build a Backend::Chroma pointing at the supervised container. Just a constructor convenience — the supervisor carries the host/port, the caller carries the collection name.

Parameters:

  • collection (String)

    Chroma collection name.

Returns:



140
141
142
# File 'lib/pikuri/vector_db/server/chroma.rb', line 140

def client(collection:)
  Backend::Chroma.new(host: 'localhost', port: @port, collection: collection)
end

#closevoid

This method returns an undefined value.

Remove the supervised container, leaving the bind-mounted #data_dir — the corpus survives. Registered with Finalizers by #ensure_running!; safe to call directly too. Best-effort and idempotent — see DockerContainer#close.



167
168
169
# File 'lib/pikuri/vector_db/server/chroma.rb', line 167

def close
  @container.close
end

#default_data_dirString

Default host-side data directory: $XDG_CACHE_HOME/pikuri/chroma if set, else ~/.cache/pikuri/chroma. Public so tests and chapter examples can reference the same path the supervisor resolves at runtime.

Returns:

  • (String)


178
179
180
# File 'lib/pikuri/vector_db/server/chroma.rb', line 178

def default_data_dir
  Pikuri::Paths.cache.join('chroma').to_s
end

#endpointString

Returns localhost:<port>”. Useful for wiring custom Backend::Chroma constructions.

Returns:

  • (String)

    localhost:<port>”. Useful for wiring custom Backend::Chroma constructions.



129
130
131
# File 'lib/pikuri/vector_db/server/chroma.rb', line 129

def endpoint
  @container.endpoint
end

#ensure_running!void

This method returns an undefined value.

Idempotent: ensure a fresh container is running and healthy (see DockerContainer#ensure_running! for the reuse-or-recreate algorithm), then register #close with Finalizers — once — so the container is removed at process exit.

Raises:

  • (RuntimeError)

    on missing docker, any docker command failure, or healthcheck timeout.



153
154
155
156
157
158
# File 'lib/pikuri/vector_db/server/chroma.rb', line 153

def ensure_running!
  FileUtils.mkdir_p(@data_dir)
  @container.ensure_running!
  @finalizer_handle ||= Pikuri::Finalizers.register(self)
  nil
end