Class: Pikuri::VectorDb::Server::Chroma
- Inherits:
-
Object
- Object
- Pikuri::VectorDb::Server::Chroma
- 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).
'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.
'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.
'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-vtarget 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.
30
Instance Attribute Summary collapse
-
#data_dir ⇒ Pathname
readonly
Host-side data directory.
-
#port ⇒ Integer
readonly
Host-side port.
Class Method Summary collapse
-
.ensure_running(data_dir: nil, port: 8000, healthcheck_timeout: DEFAULT_HEALTHCHECK_TIMEOUT) ⇒ Server::Chroma
Construct a server and immediately ensure it’s running.
Instance Method Summary collapse
-
#client(collection:) ⇒ Backend::Chroma
Build a Backend::Chroma pointing at the supervised container.
-
#close ⇒ void
Remove the supervised container, leaving the bind-mounted #data_dir — the corpus survives.
-
#default_data_dir ⇒ String
Default host-side data directory: $XDG_CACHE_HOME/pikuri/chroma if set, else ~/.cache/pikuri/chroma.
-
#endpoint ⇒ String
“localhost:<port>”.
-
#ensure_running! ⇒ void
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.
- #initialize(data_dir: nil, port: 8000, healthcheck_timeout: DEFAULT_HEALTHCHECK_TIMEOUT, connection: nil) ⇒ Server::Chroma constructor
Constructor Details
#initialize(data_dir: nil, port: 8000, healthcheck_timeout: DEFAULT_HEALTHCHECK_TIMEOUT, connection: nil) ⇒ Server::Chroma
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). @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_dir ⇒ Pathname (readonly)
Returns host-side data directory.
122 123 124 |
# File 'lib/pikuri/vector_db/server/chroma.rb', line 122 def data_dir @data_dir end |
#port ⇒ Integer (readonly)
Returns 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!).
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.
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 |
#close ⇒ void
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_dir ⇒ String
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.
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 |
#endpoint ⇒ String
Returns “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.
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 |