Class: Cosmo::API::Counter

Inherits:
Object
  • Object
show all
Defined in:
lib/cosmo/api/counter.rb,
sig/cosmo/api/counter.rbs

Constant Summary collapse

STREAM_NAME =

Returns:

  • (::String)
"_cosmostats"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(namespace) ⇒ Counter

Returns a new instance of Counter.

Parameters:

  • namespace (::String)


12
13
14
# File 'lib/cosmo/api/counter.rb', line 12

def initialize(namespace)
  @namespace = namespace
end

Class Method Details

.instanceCounter

Returns:



8
9
10
# File 'lib/cosmo/api/counter.rb', line 8

def self.instance
  @instance ||= new("jobs")
end

Instance Method Details

#clientClient

Returns:



76
77
78
# File 'lib/cosmo/api/counter.rb', line 76

def client
  @client ||= Client.instance
end

#decrement(key, by: 1, msg_id: nil) ⇒ ::Integer Also known as: decr

Parameters:

  • key (Symbol)
  • by: (::Integer) (defaults to: 1)

Returns:

  • (::Integer)


29
30
31
# File 'lib/cosmo/api/counter.rb', line 29

def decrement(key, by: 1, msg_id: nil)
  publish(key, "-#{by}", msg_id: msg_id)
end

#get(key) ⇒ ::Integer

Parameters:

  • key (Symbol)

Returns:

  • (::Integer)


39
40
41
42
43
44
# File 'lib/cosmo/api/counter.rb', line 39

def get(key)
  raw = client.get_message(STREAM_NAME, direct: true, subject: subject(key))
  Utils::Json.parse(raw.data, default: { "val" => 0 })[:val].to_i
rescue NATS::JetStream::Error::NotFound, NATS::JetStream::Error::ServiceUnavailable, NATS::IO::Timeout
  0
end

#increment(key, by: 1, msg_id: nil) ⇒ ::Integer Also known as: incr

Parameters:

  • key (Symbol)
  • by: (::Integer) (defaults to: 1)

Returns:

  • (::Integer)


24
25
26
# File 'lib/cosmo/api/counter.rb', line 24

def increment(key, by: 1, msg_id: nil)
  publish(key, "+#{by}", msg_id: msg_id)
end

#publish(key, value, msg_id: nil) ⇒ Integer?

Returns the resulting counter value, or nil when this exact msg_id was already applied (a deduped publish's PubAck carries no val at all -- coercing that to 0 would look identical to "counter is now 0", so callers must treat nil as "no new information" rather than a real value).

Parameters:

  • msg_id (String, nil) (defaults to: nil)

    when given, sent as Nats-Msg-Id so a redelivered caller (e.g. a job whose ack was lost and retried) collapses onto the stream's duplicate_window instead of double-applying the +/- delta.

  • key (Symbol)
  • value (::String)

Returns:

  • (Integer, nil)

    the resulting counter value, or nil when this exact msg_id was already applied (a deduped publish's PubAck carries no val at all -- coercing that to 0 would look identical to "counter is now 0", so callers must treat nil as "no new information" rather than a real value).



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/cosmo/api/counter.rb', line 55

def publish(key, value, msg_id: nil)
  rescued = nil
  headers = { "Nats-Incr" => value }
  headers["Nats-Msg-Id"] = msg_id if msg_id

  begin
    ack = client.publish(subject(key), "", header: headers)
    ack.val.to_i unless ack.duplicate
  rescue NATS::JetStream::Error::NoStreamResponse
    raise if rescued

    rescued = true
    client.create_stream(STREAM_NAME, subjects: ["#{STREAM_NAME}.>"], allow_msg_counter: true, allow_direct: true, description: "Cosmo statistics")
    retry
  end
end

#reset(key) ⇒ Object Also known as: purge

Parameters:

  • key (Symbol)

Returns:

  • (Object)


34
35
36
# File 'lib/cosmo/api/counter.rb', line 34

def reset(key)
  client.purge(STREAM_NAME, subject(key))
end

#subject(key) ⇒ ::String

Parameters:

  • key (Symbol)

Returns:

  • (::String)


72
73
74
# File 'lib/cosmo/api/counter.rb', line 72

def subject(key)
  "#{STREAM_NAME}.#{@namespace}.#{key}"
end

#with { ... } ⇒ void

This method returns an undefined value.

Yields:

Yield Returns:

  • (Boolean)


16
17
18
19
20
21
22
# File 'lib/cosmo/api/counter.rb', line 16

def with
  result = yield
  increment(:processed) if result == true
  increment(:failed) if result == false
rescue Exception # rubocop:disable Lint/RescueException
  increment(:failed)
end