Skip to content

Transactions

Committing a single or batch of changes, with preconditions and idempotency keys for safe retries.

LoonFS supports transactional commits within each namespace. The atomic unit of a transaction is called a “commit”.

A commit request contains a client-generated commit_id, an optional message, optional preconditions, and an ordered list of operations that commit all together or not at all. Remember to include the required Loonfs-Actor header with the actor ID. Commits are acknowledged only once durable; see Write-ahead log.

kindFields (* required)
create_directory*path, parents
create_directory_by_inode*parent_inode_id, *display_name
put_file*path, content, behavior, expected_inode_id, expected_revision_no
create_file_by_inode*parent_inode_id, *display_name, content
put_file_revision_by_inode*inode_id, content, *expected_revision_no
delete_path*path, behavior, expected_inode_id
delete_by_inode*inode_id, *expected_binding_version, behavior
move_path*source_path, *destination_path, behavior, expected_destination_inode_id, expected_destination_revision_no
move_by_inode*inode_id, *expected_binding_version, *destination_parent_inode_id, *destination_display_name, behavior, expected_destination_inode_id, expected_destination_revision_no
copy_path*source_path, *destination_path, behavior, expected_destination_inode_id, expected_destination_revision_no
undelete*inode_id, *deletion_seq, destination_path
restore_revision*path, *source_revision_no
update_attributes*path, set, remove, expected_inode_id, expected_attributes_revision_no
update_access*path, *boundary, *grants, expected_inode_id, expected_access_revision_no

For each content-writing operation, supply exactly one of content_ref (with its proof in the request’s content_tokens) or base64 inline_content. Inline writes require filesystem.commits.inline_content and must fit commit.max_inline_content_bytes_per_operation per file. See Uploads & downloads.

The commit response includes committed_seq, committed_by (the actor ID), committed_at_ms, and the commit’s events. Retries may omit events if the WAL entry has been removed.

Read more about the commit API here: Apply a commit.

LoonFS supports preconditions and uses optimistic concurrency control. This means clients may supply optional preconditions on commits so that a write only lands if the namespace still matches the state the client expects.

Depending on the operation, these preconditions include expected_revision_no, expected_inode_id, expected_attributes_revision_no, expected_access_revision_no, expected_binding_version, and the deletion_seq used for recovery. If you set expected_revision_no on put_file, include expected_inode_id too.

The request-level preconditions array checks the state before any operations run. Its kinds are namespace_head, file_revision, path_binding, path_absence, attributes_revision, and access_revision.

If a precondition fails, the whole commit is rejected. To see what failed, check details.precondition_index in the error response. For example, a value of 0 means the first item in your preconditions list failed.

This means that genuine conflicts can be handled elegantly by the client depending on the preferred behavior. For example, if two clients are racing to replace the same file content, only one transaction will commit when both supply the same expected_revision_no. The losing client can reload the current revision and decide whether to retry with a new precondition, merge the changes, or write the result to a different path.

Every named path entry carries an opaque binding_version. Supply the value last read when using move_by_inode or delete_by_inode; if that inode has been moved, deleted, or rebound, the commit fails with binding_version_mismatch instead of assuming a stale location state.

Every HTTP commit requires a commit_id for idempotency. Retry with the same ID, body, actor, and subject after a timeout or uncertain outcome. While its receipt is retained, an identical request returns the original result; changing the request returns commit_id_reuse_conflict. Once the receipt is deleted, a retry can apply the operation again.