Class: SolidObjects::Activation

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(lease:) ⇒ Activation

Returns a new instance of Activation.

RBS:

  • (lease: Lease) -> void

Parameters:



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/solid_objects/activation.rb', line 14

def initialize(lease:)
  @lease = lease
  instance = Instance.find(lease.instance_id)
  @actor_class = SolidObjects.registry.fetch(instance.actor_type)
  @actor = build_actor(instance)
  @last_used_at = monotonic_now
  @pass_exhausted = false
  actor.activate
  SolidObjects.instrument(
    :"activation.started",
    instance_id: instance.id,
    actor_type: instance.actor_type,
    actor_id: instance.actor_id,
    owner_id: lease.owner_id,
    generation: lease.generation
  )
end

Instance Attribute Details

#actorObject (readonly)

RBS:

  • @lease: Lease

  • @actor_class: Class

  • @actor: Actor

  • @last_used_at: Float

  • @pass_exhausted: bool

Returns:

  • (Object)


11
12
13
# File 'lib/solid_objects/activation.rb', line 11

def actor
  @actor
end

#actor_classObject (readonly)

Returns the value of attribute actor_class.

Returns:

  • (Object)


114
115
116
# File 'lib/solid_objects/activation.rb', line 114

def actor_class
  @actor_class
end

#leaseObject (readonly)

RBS:

  • @lease: Lease

  • @actor_class: Class

  • @actor: Actor

  • @last_used_at: Float

  • @pass_exhausted: bool

Returns:

  • (Object)


11
12
13
# File 'lib/solid_objects/activation.rb', line 11

def lease
  @lease
end

Instance Method Details

#build_actor(instance) ⇒ Actor

RBS:

  • (Instance) -> Actor

Parameters:

Returns:



117
118
119
120
121
122
123
# File 'lib/solid_objects/activation.rb', line 117

def build_actor(instance)
  state_data = actor_class.definition.migrate_state(instance.state_version, instance.state)
  actor_class.new(
    actor_id: instance.actor_id,
    state: State.new(actor_class.definition.state_definition, state_data)
  )
end

#claim_next_messageMessage?

RBS:

  • () -> Message?

Returns:



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/solid_objects/activation.rb', line 126

def claim_next_message
  lease.fenced_transaction do |instance|
    recover_stale_claim(instance)
    ready_message = ReadyMessage
      .where(instance_id: instance.id)
      .order(:sequence)
      .first
    next unless ready_message

    now = SolidObjects.database_adapter.database_now
    next if ready_message.available_at > now

    message = Message.lock.find(ready_message.message_id)
    ready_message.destroy!
    message.update!(
      attempt_count: message.attempt_count + 1,
      started_at: now
    )
    ClaimedMessage.create!(
      message:,
      instance:,
      process_id: lease.owner_id,
      activation_generation: lease.generation,
      claimed_at: now
    )
    message
  end
end

#deactivatevoid

This method returns an undefined value.

RBS:

  • () -> void



105
106
107
108
109
110
# File 'lib/solid_objects/activation.rb', line 105

def deactivate
  actor.deactivate
  lease.release
rescue LostActivation
  nil
end

#drainInteger

RBS:

  • () -> Integer

Returns:

  • (Integer)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/solid_objects/activation.rb', line 33

def drain
  processed_count = 0
  started_at = monotonic_now
  @pass_exhausted = false

  loop do
    if processed_count >= SolidObjects.configuration.max_messages_per_activation_pass ||
        monotonic_now - started_at >= SolidObjects.configuration.max_activation_duration
      @pass_exhausted = true
      break
    end

    message = claim_next_message
    break unless message

    Executor.new(activation: self, message:).call
    processed_count += 1
    @last_used_at = monotonic_now
  end

  processed_count
end

#idle?Boolean

RBS:

  • () -> bool

Returns:

  • (Boolean)


73
74
75
# File 'lib/solid_objects/activation.rb', line 73

def idle?
  monotonic_now - @last_used_at >= SolidObjects.configuration.idle_deactivation_timeout
end

#lease_renewal_due?Boolean

RBS:

  • () -> bool

Returns:

  • (Boolean)


83
84
85
86
# File 'lib/solid_objects/activation.rb', line 83

def lease_renewal_due?
  lease.expires_at - SolidObjects.database_adapter.database_now <=
    SolidObjects.configuration.lease_renewal_interval
end

#monotonic_nowFloat

RBS:

  • () -> Float

Returns:

  • (Float)


179
180
181
# File 'lib/solid_objects/activation.rb', line 179

def monotonic_now
  ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
end

#pass_exhausted?Boolean

RBS:

  • () -> bool

Returns:

  • (Boolean)


68
69
70
# File 'lib/solid_objects/activation.rb', line 68

def pass_exhausted?
  @pass_exhausted
end

#ready?Boolean

RBS:

  • () -> bool

Returns:

  • (Boolean)


57
58
59
60
61
62
63
64
65
# File 'lib/solid_objects/activation.rb', line 57

def ready?
  now = SolidObjects.database_adapter.database_now
  ReadyMessage.where(instance_id: lease.instance_id, available_at: ..now).exists? ||
    ClaimedMessage.where(
      instance_id: lease.instance_id,
      process_id: lease.owner_id,
      activation_generation: lease.generation
    ).exists?
end

#recover_stale_claim(instance) ⇒ void

This method returns an undefined value.

RBS:

  • (Instance) -> void

Parameters:



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/solid_objects/activation.rb', line 156

def recover_stale_claim(instance)
  claimed_message = ClaimedMessage
    .joins(:message)
    .where(instance_id: instance.id)
    .order("#{Message.table_name}.sequence")
    .first
  return unless claimed_message
  return if claimed_message.process_id == lease.owner_id &&
    claimed_message.activation_generation == lease.generation

  message = claimed_message.message
  claimed_message.destroy!
  return if message.completed? || message.dead?

  ReadyMessage.create!(
    message:,
    instance:,
    sequence: message.sequence,
    available_at: SolidObjects.database_adapter.database_now
  )
end

#renew_leasevoid

This method returns an undefined value.

RBS:

  • () -> void



78
79
80
# File 'lib/solid_objects/activation.rb', line 78

def renew_lease
  @lease = lease.renew
end

#restore_state(state_data) ⇒ void

This method returns an undefined value.

RBS:

  • (Hash[String, untyped]) -> void

Parameters:

  • (Hash[String, untyped])


97
98
99
100
101
102
# File 'lib/solid_objects/activation.rb', line 97

def restore_state(state_data)
  @actor = actor_class.new(
    actor_id: actor.actor_id,
    state: State.new(actor_class.definition.state_definition, state_data)
  )
end

#yield_ready_messagesvoid

This method returns an undefined value.

RBS:

  • () -> void



89
90
91
92
93
94
# File 'lib/solid_objects/activation.rb', line 89

def yield_ready_messages
  now = SolidObjects.database_adapter.database_now
  ReadyMessage
    .where(instance_id: lease.instance_id, available_at: ..now)
    .update_all(available_at: now)
end