Class: SolidObjects::Lease

Inherits:
Object
  • Object
show all
Defined in:
lib/solid_objects/lease.rb,
sig/generated/lib/solid_objects/lease.rbs

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(instance_id:, owner_id:, activation_token:, generation:, expires_at:, database_adapter:) ⇒ Lease

Returns a new instance of Lease.

RBS:

  • (instance_id: Integer, owner_id: String, activation_token: String, generation: Integer, expires_at: Time, database_adapter: DatabaseAdapter) -> void

Parameters:

  • instance_id: (Integer)
  • owner_id: (String)
  • activation_token: (String)
  • generation: (Integer)
  • expires_at: (Time)
  • database_adapter: (DatabaseAdapter)


83
84
85
86
87
88
89
90
# File 'lib/solid_objects/lease.rb', line 83

def initialize(instance_id:, owner_id:, activation_token:, generation:, expires_at:, database_adapter:)
  @instance_id = instance_id
  @owner_id = owner_id
  @activation_token = activation_token
  @generation = generation
  @expires_at = expires_at
  @database_adapter = database_adapter
end

Instance Attribute Details

#activation_tokenObject (readonly)

RBS:

  • @instance_id: Integer

  • @owner_id: String

  • @activation_token: String

  • @generation: Integer

  • @expires_at: Time

  • @database_adapter: DatabaseAdapter

Returns:

  • (Object)


80
81
82
# File 'lib/solid_objects/lease.rb', line 80

def activation_token
  @activation_token
end

#database_adapterObject (readonly)

Returns the value of attribute database_adapter.

Returns:

  • (Object)


158
159
160
# File 'lib/solid_objects/lease.rb', line 158

def database_adapter
  @database_adapter
end

#expires_atObject (readonly)

RBS:

  • @instance_id: Integer

  • @owner_id: String

  • @activation_token: String

  • @generation: Integer

  • @expires_at: Time

  • @database_adapter: DatabaseAdapter

Returns:

  • (Object)


80
81
82
# File 'lib/solid_objects/lease.rb', line 80

def expires_at
  @expires_at
end

#generationObject (readonly)

RBS:

  • @instance_id: Integer

  • @owner_id: String

  • @activation_token: String

  • @generation: Integer

  • @expires_at: Time

  • @database_adapter: DatabaseAdapter

Returns:

  • (Object)


80
81
82
# File 'lib/solid_objects/lease.rb', line 80

def generation
  @generation
end

#instance_idObject (readonly)

RBS:

  • @instance_id: Integer

  • @owner_id: String

  • @activation_token: String

  • @generation: Integer

  • @expires_at: Time

  • @database_adapter: DatabaseAdapter

Returns:

  • (Object)


80
81
82
# File 'lib/solid_objects/lease.rb', line 80

def instance_id
  @instance_id
end

#owner_idObject (readonly)

RBS:

  • @instance_id: Integer

  • @owner_id: String

  • @activation_token: String

  • @generation: Integer

  • @expires_at: Time

  • @database_adapter: DatabaseAdapter

Returns:

  • (Object)


80
81
82
# File 'lib/solid_objects/lease.rb', line 80

def owner_id
  @owner_id
end

Class Method Details

.acquire(instance_id:, owner_id:, activation_token: SecureRandom.uuid, duration: SolidObjects.configuration.lease_duration, database_adapter: SolidObjects.database_adapter) ⇒ Lease?

RBS:

  • (instance_id: Integer, owner_id: String, ?activation_token: String, ?duration: Numeric, ?database_adapter: DatabaseAdapter) -> Lease?

Parameters:

  • instance_id: (Integer)
  • owner_id: (String)
  • activation_token: (String) (defaults to: SecureRandom.uuid)
  • duration: (Numeric) (defaults to: SolidObjects.configuration.lease_duration)
  • database_adapter: (DatabaseAdapter) (defaults to: SolidObjects.database_adapter)

Returns:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/solid_objects/lease.rb', line 37

def acquire(
  instance_id:,
  owner_id:,
  activation_token: SecureRandom.uuid,
  duration: SolidObjects.configuration.lease_duration,
  database_adapter: SolidObjects.database_adapter
)
  lease = database_adapter.transaction do
    instance = Instance.lock.find(instance_id)
    now = database_adapter.database_now
    claim(instance:, owner_id:, activation_token:, now:, duration:, database_adapter:)
  end

  if lease
    SolidObjects.instrument(
      :"activation.claimed",
      instance_id:,
      owner_id:,
      generation: lease.generation
    )
  end

  lease
end

.claim(instance:, owner_id:, activation_token:, now:, database_adapter:, duration: SolidObjects.configuration.lease_duration) ⇒ Lease?

RBS:

  • (instance: Instance, owner_id: String, activation_token: String, now: Time, ?duration: Numeric, database_adapter: DatabaseAdapter) -> Lease?

Parameters:

  • instance: (Instance)
  • owner_id: (String)
  • activation_token: (String)
  • now: (Time)
  • database_adapter: (DatabaseAdapter)
  • duration: (Numeric) (defaults to: SolidObjects.configuration.lease_duration)

Returns:



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/solid_objects/lease.rb', line 7

def claim(
  instance:,
  owner_id:,
  activation_token:,
  now:,
  database_adapter:, duration: SolidObjects.configuration.lease_duration
)
  return if held_by_another_live_owner?(instance, activation_token, now)

  generation = instance.activation_generation + 1
  expires_at = now + duration
  instance.update!(
    activation_owner_id: owner_id,
    activation_token:,
    activation_expires_at: expires_at,
    activation_generation: generation,
    activated_at: now,
    last_claimed_at: now
  )
  new(
    instance_id: instance.id,
    owner_id:,
    activation_token:,
    generation:,
    expires_at:,
    database_adapter:
  )
end

Instance Method Details

#fenced_transaction {|arg0| ... } ⇒ Object

RBS:

  • () { (Instance) -> untyped } -> untyped

Yields:

Yield Parameters:

Yield Returns:

  • (Object)

Returns:

  • (Object)


148
149
150
151
152
153
154
# File 'lib/solid_objects/lease.rb', line 148

def fenced_transaction
  database_adapter.transaction do
    instance = locked_owned_instance!
    verify_unexpired!(instance, database_adapter.database_now)
    yield instance
  end
end

#locked_owned_instance!Instance

RBS:

  • () -> Instance

Returns:



161
162
163
164
165
166
167
168
# File 'lib/solid_objects/lease.rb', line 161

def locked_owned_instance!
  instance = Instance.lock.find_by(id: instance_id)
  raise ActorDestroyed, "actor instance no longer exists" unless instance

  instance.tap do
    raise LostActivation, "activation owner or generation changed" unless owned_generation?(instance)
  end
end

#owned_generation?(instance) ⇒ Boolean

RBS:

  • (Instance) -> bool

Parameters:

Returns:

  • (Boolean)


171
172
173
174
175
# File 'lib/solid_objects/lease.rb', line 171

def owned_generation?(instance)
  instance.activation_owner_id == owner_id &&
    instance.activation_token == activation_token &&
    instance.activation_generation == generation
end

#releaseBoolean

RBS:

  • () -> bool

Returns:

  • (Boolean)


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/solid_objects/lease.rb', line 121

def release
  released = database_adapter.transaction do
    instance = Instance.lock.find_by(id: instance_id)
    next false unless instance
    next false unless owned_generation?(instance)

    instance.update!(
      activation_owner_id: nil,
      activation_token: nil,
      activation_expires_at: nil
    )
    true
  end

  if released
    SolidObjects.instrument(
      :"activation.released",
      instance_id:,
      owner_id:,
      generation:
    )
  end

  released
end

#renew(duration: SolidObjects.configuration.lease_duration) ⇒ Lease

RBS:

  • (?duration: Numeric) -> Lease

Parameters:

  • duration: (Numeric) (defaults to: SolidObjects.configuration.lease_duration)

Returns:



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/solid_objects/lease.rb', line 93

def renew(duration: SolidObjects.configuration.lease_duration)
  renewed_lease = database_adapter.transaction do
    instance = locked_owned_instance!
    now = database_adapter.database_now
    verify_unexpired!(instance, now)
    renewed_expiration = now + duration
    instance.update!(activation_expires_at: renewed_expiration)

    self.class.new(
      instance_id:,
      owner_id:,
      activation_token:,
      generation:,
      expires_at: renewed_expiration,
      database_adapter:
    )
  end
  SolidObjects.instrument(
    :"activation.renewed",
    instance_id:,
    owner_id:,
    generation:,
    expires_at: renewed_lease.expires_at
  )
  renewed_lease
end

#verify_unexpired!(instance, now) ⇒ void

This method returns an undefined value.

RBS:

  • (Instance, Time) -> void

Parameters:



178
179
180
181
182
# File 'lib/solid_objects/lease.rb', line 178

def verify_unexpired!(instance, now)
  return if instance.activation_expires_at && instance.activation_expires_at > now

  raise LostActivation, "activation lease expired"
end