Class: SolidObjects::SynchronousInvocation

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

Instance Method Summary collapse

Instance Method Details

#assist(message, deadline:) ⇒ Integer

RBS:

  • (Message, deadline: Float) -> Integer

Parameters:

Returns:

  • (Integer)


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/solid_objects/synchronous_invocation.rb', line 80

def assist(message, deadline:)
  process_registry = SolidObjects.caller_process.process_registry
  activation = ActivationManager
    .new(owner_id: process_registry.process_record.id)
    .claim(instance_id: message.instance_id)
  return 0 unless activation

  LeaseRenewer.new(
    activation:,
    process_registry:
  ).around do
    activation.drain_until(message_id: message.id, deadline:)
  end
ensure
  if activation
    activation.yield_ready_messages if activation.pass_exhausted?
    activation.deactivate
  end
end

#call(message_reference, timeout:) ⇒ Object

RBS:

  • (MessageReference, timeout: Numeric) -> untyped

Parameters:

Returns:

  • (Object)


10
11
12
13
14
15
16
17
18
# File 'lib/solid_objects/synchronous_invocation.rb', line 10

def call(message_reference, timeout:)
  return call_before_deadline(message_reference, timeout:) if SyncDeadline.active?

  SyncDeadline.with(timeout:) do
    call_before_deadline(message_reference, timeout:)
  end
rescue ActiveRecord::RecordNotFound
  raise ActorDestroyed, "actor was destroyed while waiting for its result"
end

#call_before_deadline(message_reference, timeout:) ⇒ Object

RBS:

  • (MessageReference, timeout: Numeric) -> untyped

Parameters:

Returns:

  • (Object)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/solid_objects/synchronous_invocation.rb', line 23

def call_before_deadline(message_reference, timeout:)
  deadline = monotonic_now + SyncDeadline.remaining

  loop do
    message = load_message(message_reference)
    return completed_result(message) if message.completed? || message.dead?

    remaining = deadline - monotonic_now
    unless remaining.positive?
      message = load_message(message_reference)
      return completed_result(message) if message.completed? || message.dead?

      raise SyncDiagnostics.new.call(message, timeout:)
    end

    processed = assist(message, deadline:)
    remaining = deadline - monotonic_now
    wait(remaining) if processed.zero? && remaining.positive?
  end
rescue DatabaseDeadlineExceeded
  message = load_message(message_reference)
  return completed_result(message) if message.completed? || message.dead?

  raise SyncDiagnostics.new.call(message, timeout:)
end

#completed_result(message) ⇒ Object

RBS:

  • (Message) -> untyped

Parameters:

Returns:

  • (Object)


55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/solid_objects/synchronous_invocation.rb', line 55

def completed_result(message)
  raise_rejection(message) if message.rejected?
  if message.dead?
    raise MessageFailed.new(
      "actor message failed permanently",
      message_id: message.id,
      details: message.error || {}
    )
  end

  Serialization.readonly_copy(message.result)
end

#load_message(message_reference) ⇒ Message

RBS:

  • (MessageReference) -> Message

Parameters:

Returns:



50
51
52
# File 'lib/solid_objects/synchronous_invocation.rb', line 50

def load_message(message_reference)
  Message.uncached { Message.find(message_reference.id) }
end

#monotonic_nowFloat

RBS:

  • () -> Float

Returns:

  • (Float)


108
109
110
# File 'lib/solid_objects/synchronous_invocation.rb', line 108

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

#raise_rejection(message) ⇒ bot

RBS:

  • (Message) -> bot

Parameters:

Returns:

  • (bot)


69
70
71
72
73
74
75
76
77
# File 'lib/solid_objects/synchronous_invocation.rb', line 69

def raise_rejection(message)
  rejection = message.rejection
  raise Rejected.new(
    code: rejection.fetch("code"),
    message: rejection.fetch("message"),
    details: rejection.fetch("details"),
    message_id: message.id
  )
end

#wait(remaining) ⇒ void

This method returns an undefined value.

RBS:

  • (Numeric) -> void

Parameters:

  • (Numeric)


101
102
103
104
105
# File 'lib/solid_objects/synchronous_invocation.rb', line 101

def wait(remaining)
  SolidObjects.wake_up.wait(
    timeout: [ remaining, SolidObjects.configuration.sync_polling_interval ].min
  )
end