tiny_bus 1.0.4 → 3.0.0
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 +4 -4
- data/lib/tiny_bus.rb +52 -37
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33fd7e7b558ef0142c5edccdd2f680edd44b1b857a9bd6b39c6c6c554b3fc007
|
4
|
+
data.tar.gz: 75c523e3d559488de425a0ebe96c2e36253d85e226f2cc83de35c72bc56254b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e12dff36fe08ad554645939c3b5509e9f8718bbb4eedc4819a1dbb53460093459c1e77fae52b1dd6b20ae4b25fe840a06651c446c46b8dcfac81c0a8b9a065e
|
7
|
+
data.tar.gz: f30197ba6ef9502d38066d6223789c2c6dccdf704abc289b1f022e8cbc8aa75bcd14ea5c3553546d5e7ca5bb9d8f1ec63370da167d55fb576d79f1373bc73fe5
|
data/lib/tiny_bus.rb
CHANGED
@@ -2,95 +2,112 @@ require 'time'
|
|
2
2
|
require 'set'
|
3
3
|
require 'securerandom'
|
4
4
|
require 'tiny_log'
|
5
|
+
require 'tiny_pipe'
|
5
6
|
|
7
|
+
# NOTE: This library depends on the TinyLog library.
|
8
|
+
#
|
6
9
|
# This class implements a very simpler PubSub system where:
|
7
10
|
# - subscribers can subscribe via the #sub method
|
8
11
|
# - subscribers can unsubscribe via the #unsub method
|
9
12
|
# - msgs can enter the TinyBus via the #msg method
|
10
13
|
#
|
11
14
|
# The messages that come into this TinyBus are assumed to be Hash-like, in the
|
12
|
-
# sense that they have a 'topic' key that can be accessed using Hash-like key
|
13
|
-
# access syntax, and that the 'topic' key will serve as the method of
|
15
|
+
# sense that they have a '.topic' key that can be accessed using Hash-like key
|
16
|
+
# access syntax, and that the '.topic' key will serve as the method of
|
14
17
|
# distribution.
|
15
18
|
#
|
16
19
|
# Usage:
|
17
20
|
# t = TinyBus.new
|
18
21
|
# t.sub('news', <some object that responds to #msg)
|
19
|
-
# t.msg({'topic' => 'news', 'details' => 'Historic happenings!}) # goes to 'news' subscribers
|
20
|
-
# t.msg({'topic' => 'whatever', 'details' => 'Historic happenings!}) # goes to dead letter output, or raises exception, depending on the configuration
|
22
|
+
# t.msg({'.topic' => 'news', 'details' => 'Historic happenings!}) # goes to 'news' subscribers
|
23
|
+
# t.msg({'.topic' => 'whatever', 'details' => 'Historic happenings!}) # goes to dead letter output, or raises exception, depending on the configuration
|
21
24
|
#
|
22
25
|
# Initialization options:
|
23
|
-
# TinyBus.new(log: <a
|
24
|
-
# TinyBus.new(dead: <a
|
25
|
-
# TinyBus.new(raise_on_dead: true)
|
26
|
+
# TinyBus.new(log: <a TinyLog for output>) # will log all normal msgs in this file
|
27
|
+
# TinyBus.new(dead: <a TinyLog for dead messages>) # will log all undeliverable msgs in this file
|
28
|
+
# TinyBus.new(raise_on_dead: true) # strict mode for undeliverable messages, defaults to false
|
26
29
|
class TinyBus
|
27
30
|
# log:
|
28
|
-
# if specified it should be a
|
29
|
-
# if not specified will
|
31
|
+
# if specified, it should be a TinyLog instance
|
32
|
+
# if not specified, it will create a new TinyLog instance for $stdout
|
30
33
|
# dead:
|
31
|
-
# if specified it should be a
|
32
|
-
# if not specified will
|
34
|
+
# if specified, it should be a TinyLog instance
|
35
|
+
# if not specified, it will create a new TinyLog instance for $stderr
|
36
|
+
# translator:
|
37
|
+
# the translator is an instance of TinyPipe, if you want to translate the
|
38
|
+
# incoming masssage (i.e. annotate with additional fields, change
|
39
|
+
# keys/values on incoming messges). if not specified no translatioins will
|
40
|
+
# be made on incoming messages other than the default annotations
|
41
|
+
# NOTE: all messages are automatically annotated with three fields:
|
42
|
+
# - .time: the Unix time the message is received in Integer milliseconds,
|
43
|
+
# - .msg_uuid: a unique UUID for the incoming message
|
44
|
+
# - .trace: a unique UUID for chains of messages (if not present)
|
33
45
|
# raise_on_dead:
|
34
|
-
# kind of a strict mode. if false, then messages with a topic with no
|
35
|
-
# subscribers will go to the dead file. if true, then messages with a
|
36
|
-
# with no subscribers will raise an exception.
|
37
|
-
def initialize(log: nil, dead: nil, raise_on_dead: false)
|
46
|
+
# kind of a strict mode. if false, then messages with a '.topic' with no
|
47
|
+
# subscribers will go to the dead file. if true, then messages with a
|
48
|
+
# '.topic' with no subscribers will raise an exception.
|
49
|
+
def initialize(log: nil, dead: nil, translator: nil, raise_on_dead: false)
|
38
50
|
@subs = {}
|
51
|
+
@translator = translator
|
52
|
+
@annotator = TinyPipe.new([
|
53
|
+
->(m){ m['.time'] = (Time.now.to_f * 1000).to_i; m },
|
54
|
+
->(m){ m['.msg_uuid'] = SecureRandom.uuid; m },
|
55
|
+
->(m){ m['.trace'] ||= SecureRandom.uuid; m }
|
56
|
+
])
|
57
|
+
|
39
58
|
@stats = { '.dead' => 0 }
|
40
|
-
@log = log
|
41
|
-
@dead = dead
|
59
|
+
@log = log || TinyLog.new($stdout)
|
60
|
+
@dead = dead || TinyLog.new($stderr)
|
42
61
|
@raise_on_dead = raise_on_dead
|
43
62
|
end
|
44
63
|
|
45
64
|
# adds a subscriber to a topic
|
46
|
-
#
|
47
|
-
# topics can be any string that doesn't start with a dot (.) - dot topics are
|
48
|
-
# reserved for internal TinyBus usage, such as:
|
49
|
-
# - .log
|
50
65
|
def sub(topic, subber)
|
51
|
-
raise TinyBus::SubscriptionToDotTopicError.new("Cannot subscribe to dot topic `#{topic}', because those are reserved for internal use") if topic.start_with?('.')
|
52
66
|
raise TinyBus::SubscriberDoesNotMsg.new("The specified subscriber type `#{subber.class.inspect}' does not respond to #msg") unless subber.respond_to?(:msg)
|
53
67
|
|
54
68
|
@subs[topic] ||= Set.new
|
55
69
|
@subs[topic] << subber
|
56
70
|
@stats[topic] ||= 0
|
71
|
+
|
72
|
+
msg({ '.topic' => 'sub', 'to_topic' => topic, 'subber' => subber.to.s })
|
57
73
|
end
|
58
74
|
|
59
75
|
# removes a subscriber from a topic
|
60
76
|
def unsub(topic, subber)
|
61
77
|
@subs[topic]&.delete(subber)
|
78
|
+
|
79
|
+
msg({ '.topic' => 'unsub', 'from_topic' => topic, 'subber' => subber.to.s })
|
62
80
|
end
|
63
81
|
|
64
82
|
# takes an incoming message and distributes it to subscribers
|
65
83
|
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
# - .msg_uuid: a UUID to uniquely identify this message
|
84
|
+
# msg: the incoming message to be distributed
|
85
|
+
# lvl (optional): the logging level
|
69
86
|
#
|
70
87
|
# NOTE: it modifies the incoming msg object in place in order to avoid
|
71
88
|
# unnecessary object allocations
|
89
|
+
#
|
90
|
+
# NOTE: keys that begin with dot (.), such as '.time' are reserved for
|
91
|
+
# TinyBus and show not be altered by outside code, otherwise undefined
|
92
|
+
# behavior may result.
|
72
93
|
def msg(msg, lvl='info')
|
73
|
-
|
94
|
+
msg = @annotator.pipe(msg)
|
95
|
+
msg = @translator&.pipe(msg) || msg
|
74
96
|
|
75
|
-
|
97
|
+
topic = msg['topic']
|
76
98
|
|
77
99
|
subbers = @subs[topic]
|
78
100
|
|
79
|
-
annotated = msg.merge!({
|
80
|
-
'.time' => Time.now.utc.iso8601(6),
|
81
|
-
'.msg_uuid' => SecureRandom.uuid
|
82
|
-
})
|
83
|
-
|
84
101
|
if subbers
|
85
102
|
@stats[topic] += 1
|
86
|
-
subbers.each{|s| s.msg(
|
87
|
-
@log.sent
|
103
|
+
subbers.each{|s| s.msg(msg) }
|
104
|
+
@log.sent msg
|
88
105
|
else
|
89
106
|
if @raise_on_dead
|
90
107
|
raise TinyBus::DeadMsgError.new("Could not deliver message to topic `#{topic}'")
|
91
108
|
else
|
92
109
|
@stats['.dead'] += 1
|
93
|
-
@dead.dead
|
110
|
+
@dead.dead msg
|
94
111
|
end
|
95
112
|
end
|
96
113
|
end
|
@@ -106,6 +123,4 @@ class TinyBus
|
|
106
123
|
end
|
107
124
|
|
108
125
|
class TinyBus::DeadMsgError < RuntimeError; end
|
109
|
-
class TinyBus::SubscriptionToDotTopicError < RuntimeError; end
|
110
126
|
class TinyBus::SubscriberDoesNotMsg < RuntimeError; end
|
111
|
-
class TinyBus::SendToDotTopicError< RuntimeError; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_bus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Lunt
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tiny_log
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tiny_pipe
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
description: a tiny pubsub message bus with almost no features
|
28
42
|
email: jefflunt@gmail.com
|
29
43
|
executables: []
|
@@ -35,7 +49,7 @@ homepage: https://github.com/jefflunt/tiny_bus
|
|
35
49
|
licenses:
|
36
50
|
- MIT
|
37
51
|
metadata: {}
|
38
|
-
post_install_message:
|
52
|
+
post_install_message:
|
39
53
|
rdoc_options: []
|
40
54
|
require_paths:
|
41
55
|
- lib
|
@@ -50,8 +64,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
64
|
- !ruby/object:Gem::Version
|
51
65
|
version: '0'
|
52
66
|
requirements: []
|
53
|
-
rubygems_version: 3.
|
54
|
-
signing_key:
|
67
|
+
rubygems_version: 3.3.7
|
68
|
+
signing_key:
|
55
69
|
specification_version: 4
|
56
70
|
summary: want to have an in-memory message bus that takes hash-like objects and distributes
|
57
71
|
them out to subscribers based on a 'topic' key, with logging to $stdout or a file,
|