Class: OllamaAgent::Runtime::CASGuard

Inherits:
Object
  • Object
show all
Defined in:
lib/ollama_agent/runtime/cas_guard.rb

Overview

Compare-and-swap helper for AtomicMutator: fencing lease + content precondition.

Content digests use SHA256 over raw bytes. When current_content_or_nil is nil (path absent on disk), the digest is the same as for an empty file (+SHA256(“”)+) so a missing file and a zero-byte file are indistinguishable by hash alone. To require absence, use expected_pre_hash: NEW_FILE_SENTINEL (+“new_file”+).

Constant Summary collapse

NEW_FILE_SENTINEL =
"__new_file__"

Class Method Summary collapse

Class Method Details

.check(current_content_or_nil:, expected_pre_hash:, fencing_token_provided:, fencing_token_current:) ⇒ :ok, ...

Returns:

  • (:ok, :stale_token, :precondition_failed)


17
18
19
20
21
22
# File 'lib/ollama_agent/runtime/cas_guard.rb', line 17

def self.check(current_content_or_nil:, expected_pre_hash:, fencing_token_provided:,
               fencing_token_current:)
  return :stale_token unless fence_allows?(fencing_token_provided, fencing_token_current)

  pre_hash_result(expected_pre_hash, current_content_or_nil)
end

.fence_allows?(provided, allocated) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
27
28
29
30
31
# File 'lib/ollama_agent/runtime/cas_guard.rb', line 24

def self.fence_allows?(provided, allocated)
  prov = provided.to_i
  curr = allocated.to_i
  return false if prov < 1
  return false if curr < 2

  prov == curr - 1
end

.pre_hash_result(expected, current_content_or_nil) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/ollama_agent/runtime/cas_guard.rb', line 33

def self.pre_hash_result(expected, current_content_or_nil)
  if expected == NEW_FILE_SENTINEL
    return :ok if current_content_or_nil.nil?

    return :precondition_failed
  end

  actual = sha256_hex_for_content(current_content_or_nil)
  return :ok if actual == expected

  :precondition_failed
end

.sha256_hex_for_content(content_or_nil) ⇒ Object



46
47
48
49
# File 'lib/ollama_agent/runtime/cas_guard.rb', line 46

def self.sha256_hex_for_content(content_or_nil)
  bytes = content_or_nil.nil? ? +"" : content_or_nil.b
  Digest::SHA256.hexdigest(bytes)
end