Class: Lemans::Environments::Daytona::SnapshotStore

Inherits:
Object
  • Object
show all
Includes:
Retries
Defined in:
lib/lemans/environments/daytona/snapshot_store.rb

Overview

Content-named snapshots: one build per image digest × resource shape, reused forever after.

Constant Summary collapse

POLL_INTERVAL_SEC =
2
SNAPSHOT_FAILED =
[
  ::DaytonaApiClient::SnapshotState::ERROR,
  ::DaytonaApiClient::SnapshotState::BUILD_FAILED
].freeze
LOCKS =

Two trials that want the same missing snapshot must not both build it; across processes the name collision settles it and the loser waits.

Concurrent::Map.new

Constants included from Retries

Retries::READ_ATTEMPTS, Retries::RETRY_DELAY_SEC, Retries::SDK_ERRORS

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client:, image:, resources:, build_timeout_sec:, logger: nil) ⇒ SnapshotStore

Returns a new instance of SnapshotStore.



31
32
33
34
35
36
37
# File 'lib/lemans/environments/daytona/snapshot_store.rb', line 31

def initialize(client:, image:, resources:, build_timeout_sec:, logger: nil)
  @client = client
  @image = image
  @resources = resources
  @build_timeout_sec = build_timeout_sec
  @logger = logger
end

Class Method Details

.lock(name) ⇒ Object



27
28
29
# File 'lib/lemans/environments/daytona/snapshot_store.rb', line 27

def self.lock(name)
  LOCKS.compute_if_absent(name) { Mutex.new }
end

Instance Method Details

#callObject



39
40
41
42
43
44
45
46
# File 'lib/lemans/environments/daytona/snapshot_store.rb', line 39

def call
  self.class.lock(name).synchronize do
    existing = find(name)
    existing = discard(existing) if existing && SNAPSHOT_FAILED.include?(existing.state)
    existing ? await_ready(existing) : build(name)
  end
  name
end

#nameObject

The lookup name and the whole reuse policy: image digest plus resource shape, because a sandbox inherits resources from its snapshot.



50
51
52
53
54
55
# File 'lib/lemans/environments/daytona/snapshot_store.rb', line 50

def name
  @name ||= begin
    shape = [image.digest, resources.cpus, resources.memory_mb, resources.storage_mb].join(":")
    "lemans-#{Digest::SHA256.hexdigest(shape)[0, 32]}"
  end
end