ration 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ccdac579175651f9ae74c5334d16cdd199e2019fe538bb717938c3749de726a
4
- data.tar.gz: 180279e4a5276f3a7258f7e507d1ae3c4cf495eacf8ab661d1896bb658216b19
3
+ metadata.gz: 06d085f3d4d3bd600254eb694a8e3052e231166adfa65c4af78b0447c7f1bd7e
4
+ data.tar.gz: bb65889b2ba23c9817f30a46de4e1eef18342684e05d6c404ffd6e26fb2ff9d1
5
5
  SHA512:
6
- metadata.gz: 22c49c8344b06a2c8a169cdfa219d23ad1372bf4e2bdcc06f762937e08409e755829d0e883ac6ff78e523f39d0e57a25b8e5191ac62981986c20c8e6f7e55e36
7
- data.tar.gz: 3f655214bf8f81d2c1e0097a5e8e71b101bf148c499da5fbd1c63f7d0b997a01dafdf0f2685a9f6a2f7740e444740c25c47b60437140e3eea573e2d34226caab
6
+ metadata.gz: a6607e53d4fcc195b113dc6a31f30789ced563d9ebfba9958b5a685c9a239eb1c2ed9a7dcf196c4c21b2f41169ac3cb109bf9b48e84a079883d8caf8f9500916
7
+ data.tar.gz: 619058a038310db757089ddb2c54373f1d4fa8d3dfbb3ad75e48422bf329f85c6984f1b8180afc2cbf85aaec876e5f697a5b47c4f4d513dee3ed979785e05fd9
@@ -9,7 +9,7 @@ module Ration
9
9
  @max_payload_bytes = max_payload_bytes
10
10
  @sync = sync
11
11
  @logger = logger || Logger.new($stderr)
12
- @queue = nil
12
+ @queue = Queue.new
13
13
  @thread = nil
14
14
  end
15
15
 
@@ -27,7 +27,6 @@ module Ration
27
27
  return if @sync
28
28
  return if @thread
29
29
 
30
- @queue = Queue.new
31
30
  @thread = Thread.new {
32
31
  while (event = @queue.pop)
33
32
  begin
@@ -42,9 +41,9 @@ module Ration
42
41
  def stop
43
42
  return if @sync
44
43
 
45
- @queue&.close
44
+ @queue.close
46
45
  @thread&.join
47
- @queue = nil
46
+ @queue = Queue.new
48
47
  @thread = nil
49
48
  end
50
49
  end
@@ -23,7 +23,7 @@ module Ration
23
23
  @channel = channel
24
24
  @max_payload_bytes = max_payload_bytes
25
25
  @poll_interval = poll_interval
26
- @publish_with = publish_with
26
+ @publish_with = publish_with || method(:publish_direct)
27
27
  @logger = logger || Logger.new($stderr)
28
28
  @thread = nil
29
29
  @stop = false
@@ -33,16 +33,7 @@ module Ration
33
33
  payload = event.to_json
34
34
  check_payload_size!(payload, @max_payload_bytes)
35
35
 
36
- if @publish_with
37
- @publish_with.call(@channel, payload)
38
- else
39
- conn = PG.connect(@url)
40
- begin
41
- conn.exec_params('SELECT pg_notify($1, $2)', [@channel, payload])
42
- ensure
43
- conn.close
44
- end
45
- end
36
+ @publish_with.call(@channel, payload)
46
37
  end
47
38
 
48
39
  def start
@@ -61,6 +52,15 @@ module Ration
61
52
 
62
53
  private
63
54
 
55
+ def publish_direct(channel, payload)
56
+ conn = PG.connect(@url)
57
+ begin
58
+ conn.exec_params('SELECT pg_notify($1, $2)', [channel, payload])
59
+ ensure
60
+ conn.close
61
+ end
62
+ end
63
+
64
64
  def connect_and_listen
65
65
  conn = PG.connect(@url)
66
66
  conn.exec("LISTEN #{conn.escape_identifier(@channel)}")
@@ -23,9 +23,9 @@ module Ration
23
23
  @channel = channel
24
24
  @max_payload_bytes = max_payload_bytes
25
25
  @poll_interval = poll_interval
26
- @publish_with = publish_with
27
- @logger = logger || Logger.new($stderr)
28
26
  @config = RedisClient.config(url: url)
27
+ @publish_with = publish_with || method(:publish_direct)
28
+ @logger = logger || Logger.new($stderr)
29
29
  @thread = nil
30
30
  @stop = false
31
31
  end
@@ -34,16 +34,7 @@ module Ration
34
34
  payload = event.to_json
35
35
  check_payload_size!(payload, @max_payload_bytes)
36
36
 
37
- if @publish_with
38
- @publish_with.call(@channel, payload)
39
- else
40
- client = @config.new_client
41
- begin
42
- client.call('PUBLISH', @channel, payload)
43
- ensure
44
- client.close
45
- end
46
- end
37
+ @publish_with.call(@channel, payload)
47
38
  end
48
39
 
49
40
  def start
@@ -62,6 +53,15 @@ module Ration
62
53
 
63
54
  private
64
55
 
56
+ def publish_direct(channel, payload)
57
+ client = @config.new_client
58
+ begin
59
+ client.call('PUBLISH', channel, payload)
60
+ ensure
61
+ client.close
62
+ end
63
+ end
64
+
65
65
  def subscribe_client
66
66
  client = @config.new_client
67
67
  pubsub = client.pubsub
@@ -3,6 +3,7 @@ require 'securerandom'
3
3
  module Ration
4
4
  class Subscription
5
5
  OVERFLOW_POLICIES = %i[close drop_oldest].freeze
6
+ DEFAULT_FILTER = ->(_event) { true }
6
7
 
7
8
  attr_reader :id
8
9
 
@@ -13,7 +14,7 @@ module Ration
13
14
 
14
15
  @id = SecureRandom.uuid
15
16
  @queue = SizedQueue.new(max)
16
- @filter = filter
17
+ @filter = filter || DEFAULT_FILTER
17
18
  @on_overflow = on_overflow
18
19
  @logger = logger
19
20
  end
@@ -59,8 +60,6 @@ module Ration
59
60
  private
60
61
 
61
62
  def passes_filter?(event)
62
- return true if @filter.nil?
63
-
64
63
  @filter.call(event)
65
64
  rescue => e
66
65
  @logger.error("Ration filter raised, closing subscription #{@id}: #{e.class}: #{e.message}")
@@ -1,3 +1,3 @@
1
1
  module Ration
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
data/lib/ration.rb CHANGED
@@ -11,12 +11,11 @@ module Ration
11
11
  def configure
12
12
  yield config
13
13
 
14
- if config.backend.nil?
14
+ backend = config.backend or
15
15
  raise NotConfigured, 'No backend configured. Set config.backend to a Ration::Backends::* instance.'
16
- end
17
16
 
18
17
  @hub&.stop
19
- @hub = Hub.new(backend: config.backend, logger: config.logger)
18
+ @hub = Hub.new(backend: backend, logger: config.logger)
20
19
  end
21
20
 
22
21
  def config
@@ -27,8 +26,8 @@ module Ration
27
26
  hub.publish(event)
28
27
  end
29
28
 
30
- def subscribe(**kwargs, &block)
31
- hub.subscribe(**kwargs, &block)
29
+ def subscribe(...)
30
+ hub.subscribe(...) # steep:ignore UnresolvedOverloading
32
31
  end
33
32
 
34
33
  def unsubscribe(sub)
@@ -44,9 +43,7 @@ module Ration
44
43
  private
45
44
 
46
45
  def hub
47
- raise NotConfigured, 'Ration is not configured. Call Ration.configure first.' unless @hub
48
-
49
- @hub
46
+ @hub or raise NotConfigured, 'Ration is not configured. Call Ration.configure first.'
50
47
  end
51
48
  end
52
49
  end
data/sig/external.rbs ADDED
@@ -0,0 +1,19 @@
1
+ module PG
2
+ class Error < StandardError
3
+ end
4
+
5
+ def self.connect: (String) -> untyped
6
+ end
7
+
8
+ module RedisClient
9
+ class Error < StandardError
10
+ end
11
+
12
+ def self.config: (**untyped) -> untyped
13
+ end
14
+
15
+ module Concurrent
16
+ class Map[unchecked out K, unchecked out V]
17
+ def clear: () -> self
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Ration
2
+ module Backends
3
+ class Base
4
+ DEFAULT_MAX_PAYLOAD_BYTES: Integer
5
+
6
+ @on_event: ^(Ration::event) -> void | nil
7
+
8
+ def publish: (Ration::event) -> void
9
+ def on_event: () { (Ration::event) -> void } -> (^(Ration::event) -> void)
10
+ def start: () -> void
11
+ def stop: () -> void
12
+
13
+ private
14
+
15
+ def emit: (Ration::event) -> void
16
+ def check_payload_size!: (String, Integer) -> void
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module Ration
2
+ module Backends
3
+ class Memory < Base
4
+ @max_payload_bytes: Integer
5
+ @sync: bool
6
+ @logger: Logger
7
+ @queue: Thread::Queue
8
+ @thread: Thread?
9
+
10
+ def initialize: (?max_payload_bytes: Integer, ?sync: bool, ?logger: Logger?) -> void
11
+ def publish: (Ration::event) -> void
12
+ def start: () -> void
13
+ def stop: () -> void
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,42 @@
1
+ module Ration
2
+ module Backends
3
+ class Postgres < Base
4
+ DEFAULT_CHANNEL: String
5
+ INITIAL_BACKOFF_SECONDS: Integer
6
+ MAX_BACKOFF_SECONDS: Integer
7
+ DEFAULT_POLL_INTERVAL: Float
8
+
9
+ type publish_with = ^(String, String) -> void
10
+
11
+ @url: String
12
+ @channel: String
13
+ @max_payload_bytes: Integer
14
+ @poll_interval: Numeric
15
+ @publish_with: publish_with
16
+ @logger: Logger
17
+ @thread: Thread?
18
+ @stop: bool
19
+
20
+ def initialize: (
21
+ url: String,
22
+ ?channel: String,
23
+ ?max_payload_bytes: Integer,
24
+ ?poll_interval: Numeric,
25
+ ?publish_with: publish_with?,
26
+ ?logger: Logger?
27
+ ) -> void
28
+
29
+ def publish: (Ration::event) -> void
30
+ def start: () -> void
31
+ def stop: () -> void
32
+
33
+ private
34
+
35
+ def publish_direct: (String, String) -> void
36
+ def connect_and_listen: () -> untyped
37
+ def run_loop: (untyped) -> void
38
+ def reconnect_with_backoff: () -> untyped
39
+ def listen_loop: (untyped) -> void
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,44 @@
1
+ module Ration
2
+ module Backends
3
+ class Redis < Base
4
+ DEFAULT_CHANNEL: String
5
+ INITIAL_BACKOFF_SECONDS: Integer
6
+ MAX_BACKOFF_SECONDS: Integer
7
+ DEFAULT_POLL_INTERVAL: Float
8
+
9
+ type publish_with = ^(String, String) -> void
10
+
11
+ @url: String
12
+ @channel: String
13
+ @max_payload_bytes: Integer
14
+ @poll_interval: Numeric
15
+ @publish_with: publish_with
16
+ @logger: Logger
17
+ @config: untyped
18
+ @thread: Thread?
19
+ @stop: bool
20
+
21
+ def initialize: (
22
+ url: String,
23
+ ?channel: String,
24
+ ?max_payload_bytes: Integer,
25
+ ?poll_interval: Numeric,
26
+ ?publish_with: publish_with?,
27
+ ?logger: Logger?
28
+ ) -> void
29
+
30
+ def publish: (Ration::event) -> void
31
+ def start: () -> void
32
+ def stop: () -> void
33
+
34
+ private
35
+
36
+ def publish_direct: (String, String) -> void
37
+ def subscribe_client: () -> untyped
38
+ def run_loop: (untyped) -> void
39
+ def reconnect_with_backoff: () -> untyped
40
+ def listen_loop: (untyped) -> void
41
+ def close_quietly: (untyped) -> void
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,8 @@
1
+ module Ration
2
+ class Configuration
3
+ attr_accessor backend: Backends::Base?
4
+ attr_accessor logger: Logger
5
+
6
+ def initialize: () -> void
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ module Ration
2
+ class Error < StandardError
3
+ end
4
+
5
+ class PayloadTooLarge < Error
6
+ end
7
+
8
+ class NotConfigured < Error
9
+ end
10
+ end
@@ -0,0 +1,22 @@
1
+ module Ration
2
+ class Hub
3
+ @backend: Backends::Base
4
+ @logger: Logger
5
+ @subscriptions: Concurrent::Map[String, Subscription]
6
+ @started: bool
7
+ @start_mutex: Thread::Mutex
8
+
9
+ def initialize: (backend: Backends::Base, logger: Logger) -> void
10
+ def publish: (Ration::event) -> void
11
+ def subscribe: (max: Integer, ?filter: Ration::filter?, ?on_overflow: Symbol) -> Subscription
12
+ | [T] (max: Integer, ?filter: Ration::filter?, ?on_overflow: Symbol) { (Subscription) -> T } -> T
13
+ def unsubscribe: (Subscription) -> void
14
+ def stop: () -> void
15
+ def subscription_count: () -> Integer
16
+
17
+ private
18
+
19
+ def ensure_started: () -> void
20
+ def deliver: (Ration::event) -> void
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module Ration
2
+ module Rails
3
+ interface _Response
4
+ def headers: () -> Hash[String, String]
5
+ end
6
+
7
+ interface _Request
8
+ def headers: () -> Hash[String, untyped]
9
+ def env: () -> Hash[String, untyped]
10
+ end
11
+
12
+ interface _Controller
13
+ def response: () -> _Response
14
+ def request: () -> _Request
15
+ def response_body=: (untyped) -> void
16
+ end
17
+
18
+ module SSE : _Controller
19
+ def sse_stream: () { (Enumerator::Yielder, String?) -> void } -> void
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ module Ration
2
+ module SSE
3
+ interface _Output
4
+ def <<: (String) -> void
5
+ end
6
+
7
+ type id_from = ^(Ration::event) -> untyped
8
+
9
+ DEFAULT_ID_FROM: id_from
10
+
11
+ def self.event: (data: untyped, ?event: String?, ?id: untyped, ?retry_ms: Integer?) -> String
12
+ def self.comment: (?String) -> String
13
+ def self.ping: () -> String
14
+ def self.stream: (
15
+ Subscription,
16
+ _Output,
17
+ ?heartbeat: _ToF?,
18
+ ?since: untyped,
19
+ ?id_from: id_from
20
+ ) { (Ration::event) -> String? } -> untyped
21
+
22
+ private
23
+
24
+ def self.ensure_field_value_safe!: (String, String) -> void
25
+ def self.ensure_no_newline!: (String, String) -> void
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ module Ration
2
+ class Subscription
3
+ OVERFLOW_POLICIES: Array[Symbol]
4
+ DEFAULT_FILTER: Ration::filter
5
+
6
+ attr_reader id: String
7
+
8
+ @queue: Thread::SizedQueue
9
+ @filter: Ration::filter
10
+ @on_overflow: Symbol
11
+ @logger: Logger
12
+
13
+ def initialize: (max: Integer, ?filter: Ration::filter?, ?on_overflow: Symbol, logger: Logger) -> void
14
+ def pop: (?timeout: _ToF?) -> Ration::event?
15
+ def each_event: (?timeout: _ToF?) -> Enumerator[Ration::event?, self]
16
+ | (?timeout: _ToF?) { (Ration::event?) -> void } -> self
17
+ def closed?: () -> bool
18
+ def close: () -> void
19
+ def deliver: (Ration::event) -> void
20
+
21
+ private
22
+
23
+ def passes_filter?: (Ration::event) -> boolish
24
+ def handle_overflow: (Ration::event) -> void
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Ration
2
+ VERSION: String
3
+ end
data/sig/ration.rbs ADDED
@@ -0,0 +1,19 @@
1
+ module Ration
2
+ type event = Hash[Symbol, untyped]
3
+ type filter = ^(event) -> boolish
4
+
5
+ self.@config: Configuration?
6
+ self.@hub: Hub?
7
+
8
+ def self.configure: () { (Configuration) -> void } -> void
9
+ def self.config: () -> Configuration
10
+ def self.publish: (event) -> void
11
+ def self.subscribe: (max: Integer, ?filter: filter?, ?on_overflow: Symbol) -> Subscription
12
+ | [T] (max: Integer, ?filter: filter?, ?on_overflow: Symbol) { (Subscription) -> T } -> T
13
+ def self.unsubscribe: (Subscription) -> void
14
+ def self.reset!: () -> void
15
+
16
+ private
17
+
18
+ def self.hub: () -> Hub
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ration
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keita Urashima
@@ -58,6 +58,19 @@ files:
58
58
  - lib/ration/sse.rb
59
59
  - lib/ration/subscription.rb
60
60
  - lib/ration/version.rb
61
+ - sig/external.rbs
62
+ - sig/ration.rbs
63
+ - sig/ration/backends/base.rbs
64
+ - sig/ration/backends/memory.rbs
65
+ - sig/ration/backends/postgres.rbs
66
+ - sig/ration/backends/redis.rbs
67
+ - sig/ration/configuration.rbs
68
+ - sig/ration/errors.rbs
69
+ - sig/ration/hub.rbs
70
+ - sig/ration/rails.rbs
71
+ - sig/ration/sse.rbs
72
+ - sig/ration/subscription.rbs
73
+ - sig/ration/version.rbs
61
74
  homepage: https://github.com/ursm/ration
62
75
  licenses:
63
76
  - MIT