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)


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/solid_objects/synchronous_invocation.rb', line 61

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)


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/solid_objects/synchronous_invocation.rb', line 9

def call(message_reference, timeout:)
  deadline = monotonic_now + timeout.to_f

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

    remaining = deadline - monotonic_now
    unless remaining.positive?
      raise SyncTimeout, "actor invocation timed out after #{timeout} seconds"
    end

    processed = assist(message, deadline:)
    wait(remaining) if processed.zero?
  end
rescue ActiveRecord::RecordNotFound
  raise ActorDestroyed, "actor was destroyed while waiting for its result"
end

#completed_result(message) ⇒ Object

RBS:

  • (Message) -> untyped

Parameters:

Returns:

  • (Object)


36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/solid_objects/synchronous_invocation.rb', line 36

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:



31
32
33
# File 'lib/solid_objects/synchronous_invocation.rb', line 31

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

#monotonic_nowFloat

RBS:

  • () -> Float

Returns:

  • (Float)


89
90
91
# File 'lib/solid_objects/synchronous_invocation.rb', line 89

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

#raise_rejection(message) ⇒ bot

RBS:

  • (Message) -> bot

Parameters:

Returns:

  • (bot)


50
51
52
53
54
55
56
57
58
# File 'lib/solid_objects/synchronous_invocation.rb', line 50

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)


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

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