In short: four flags (--host, --port, --store-type,
--sqlite-path), and only the memory store runs. Writes compute their object's ID
server-side, except WriteCommit, which keeps a commit ID the client supplies. Reads return the
stored object, a synthesized root, or NotFound. Symlink RPCs return
Unimplemented. Registration hands out a random UUID per repository and keeps it only in
memory, so a restart forgets every repository.
The crate is jj-commit-cloud-server, and its binary is jj-cc-server
(server/Cargo.toml). The wire messages are on
protobufs, the hashing on
object-ids, and the clients of these RPCs on
client-backend and
client-op-store.
Command-line arguments
| Flag | Type | Default | Effect |
|---|---|---|---|
--host | string | 127.0.0.1 | Interface to bind. |
-p, --port | u16 | 8080 | Port. 0 picks a free one, and the log line shows which. |
--store-type | memory | sqlite | memory | sqlite prints "SQLite storage backend is not yet implemented" and exits with status 1. |
--sqlite-path | path | none | Parsed but never read. Its help text names ~/.jj-cc-server/commit_cloud.db as the default. |
StoreType and Args · store selection
Startup
- Logging goes to stdout through
tracing_subscriber, filtered byRUST_LOGplus ajj_cc_server=infodirective (L62–68). - The arguments are parsed, and a SQLite request exits (L70–77).
- The health reporter marks the overall service
""andOpStoreServiceasServing.BackendServiceis never given a status, so a health check naming it gets an error rather thanServing(L81–87). - A
TcpListenerbindshost:portand logs the actual address (L89–91). CommitCloudServerImpl::default()creates oneArc<dyn Store>around a freshMemoryStore. Both services get a clone of thatArc(L48–58, L94–96).Server::builder()adds the three services and serves until Ctrl-C, then shuts down gracefully (L98–115).
The server sets no TLS, authentication, message-size limits or timeouts, so tonic's defaults apply.
Repository registration
RegisterRepository ignores its request, including the
optional name, generates a random version-4 UUID, adds it to the store's set of registered
repositories (register_repo), and returns it as
repo_id. The client calls it once, while the backend's init runs, and writes the
ID into config.toml (cc_backend.rs;
see client-backend). Each
jj cc init therefore makes a new, empty repository. There is no RPC to list or delete
repositories, and no way for two clients to share a repo ID other than copying the config.
Every other RPC calls ensure_repo_registered_error,
which returns NotFound with "repository should have been registered before …" when the ID
is unknown. Since the registered set lives in memory, every repository is unknown after a restart, and
existing clients get NotFound on every call.
BackendService, RPC by RPC
| RPC | Validation | What it does | Errors | Source |
|---|---|---|---|---|
RegisterRepository | None | See above. | None | L25 |
ReadCommit | Repo registered | Returns the stored commit. The root commit isn't synthesized; the client answers it locally. | NotFound | L35 |
WriteCommit | Repo registered, then commit present | If commit_id is empty, computes it with compute_git_commit_hash. Otherwise keeps the client's ID unchecked. Stores the commit under that ID and returns it. | NotFound, InvalidArgument | L55 |
ReadTree | Repo registered | The empty tree ID (EMPTY_TREE_ID_BYTES) returns no entries without a lookup. Otherwise returns the stored entries. | NotFound | L80 |
WriteTree | Repo registered | Computes the ID with compute_git_tree_hash and stores the entries. | NotFound | L108 |
ReadFile | Repo registered | Server-streaming in the proto, but sends the whole file as one chunk, from a spawned task over a channel of capacity 1. | NotFound | L124 |
WriteFile | Repo registered | Unary. Computes the ID with compute_git_blob_hash and stores the bytes. A TODO says large files (over 4 MB) need a streaming upload. | NotFound | L151 |
ReadSymlink, WriteSymlink | None | Not implemented. | Unimplemented | L169 |
Writes are idempotent by construction: writing the same object twice computes the same ID and overwrites the entry with identical data. A client-supplied commit ID is the exception. Nothing stops two different commits from being stored under one ID, and the later write wins (see object-ids). A file-level TODO asks for logging of file and operation IDs (L1).
OpStoreService, RPC by RPC
| RPC | Validation | What it does | Errors | Source |
|---|---|---|---|---|
ReadOperation | Repo registered | Returns the stored operation. Failing that, the root ID gets a synthesized root operation. | NotFound | L25 |
WriteOperation | operation present, then repo registered | Computes the ID with hash_operation and stores the operation. | InvalidArgument, NotFound | L78 |
ReadView | Repo registered | Returns the stored view. Failing that, the root ID gets a view whose only head is the root commit. | NotFound | L103 |
WriteView | view present, then repo registered | Computes the ID with hash_view and stores the view. | InvalidArgument, NotFound | L143 |
GetOpHeads | Repo registered | Returns the stored heads, or [root operation] if none were ever written. | NotFound | L165 |
UpdateOpHeads | Repo registered | Passes old_op_head_ids and new_op_head_id to the store, and returns the resulting heads. | NotFound | L186 |
The root operation and view are written out on
client-op-store, along with what the
store's update rule does to concurrent publishes. The store itself (the
Store trait and MemoryStore) is covered on the
storage page. Every op-store RPC logs one info line with the repo ID, and reads also log
the hex ID.
Status codes
| Code | When |
|---|---|
NotFound | Unregistered repo ID (error_util.rs), or an object that isn't stored and isn't a synthesized root. |
InvalidArgument | WriteCommit, WriteOperation or WriteView without its object. |
Unimplemented | ReadSymlink, WriteSymlink. |
Nothing checks ID lengths, the shape of a commit or tree, or whether referenced objects exist. A commit can name parents or a tree the server has never seen, and an operation can name a view that isn't stored.
What the server doesn't do
- Only the in-memory store exists. Repositories, objects and op heads are lost on restart.
--store-type sqliteexits, and--sqlite-pathis unused. - No authentication, TLS, quotas, or per-repository access control. Anyone with a repo ID can read and write it.
- No validation of IDs, object contents or references, and client-supplied commit IDs are trusted.
- Symlinks are unimplemented, and files travel as single messages either way.
- No RPC lists, deletes or garbage-collects anything.
BackendServiceisn't registered with the health service.