rmessage 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 027c26a46e85945a595e17f63f468b7db4bbc5445e62337e72aba85136ebd089
4
+ data.tar.gz: 5059e66328f264c26c20d42ab152dc4d1486b02f7990a87dec54560f94455def
5
+ SHA512:
6
+ metadata.gz: a7a1371e9e285c7f8313478f8ee7ecdce68d90b411922ed321d634781122a375534278439bfa02c175bfd1448212f08008339ada3b73e23306d27554e56cde21
7
+ data.tar.gz: ffdc5a57b6e9d5a99f9f22536478c45287076cc03a1fa2ac6ce25778f90b8b9e3f3ea316632a7d771c995f6c97e912ab479f4181010c2ee696513b3d415718b7
@@ -0,0 +1,81 @@
1
+ module RMessage
2
+ # A Message encapsulates a JSON payload that is sent to or received from Redis.
3
+ class Message
4
+
5
+ # @!attribute [r] label
6
+ # @return [Symbol, String] the label.
7
+ attr :label
8
+
9
+ # @!attribute [r] signature
10
+ # @return [Integer, String] the signature.
11
+ attr :signature
12
+
13
+ # @!attribute [r] payload
14
+ # @return [Hash] the payload.
15
+ attr :payload
16
+
17
+ # Constructs a new Message
18
+ # @param opts [Hash] message options
19
+ # * label [Symbol, String] the Message label
20
+ # * signature [Integer, String] the Message signature
21
+ # * payload [Hash, String] the Message data
22
+ # @param data [Hash, String] message data
23
+ def initialize(opts = {}, data = nil)
24
+ @label = opts[:label] || :UNTITLED
25
+ @signature = opts[:signature] || Druuid.gen
26
+ @payload = data || opts[:payload]
27
+ end
28
+
29
+ # Read and parse data. Defaults to the Message#payload.
30
+ # @param data [Hash, String] the data.
31
+ def read(data = @payload)
32
+ case data
33
+ when Hash
34
+ @label ||= data[:label]
35
+ @signature ||= data[:signature]
36
+ @payload ||= data[:payload]
37
+ when String
38
+ parsed = Oj.load(data)
39
+ @label ||= parsed['label']
40
+ @signature ||= parsed['signature']
41
+ @payload ||= parsed['payload']
42
+ else raise TypeError, 'Invalid type for Message#payload'
43
+ end
44
+ end
45
+
46
+ # Build a JSON string using data in this message
47
+ # @param data [Hash, String] the payload.
48
+ def build(data = @payload)
49
+ Oj.dump({ 'label' => @label, 'signature' => @signature, 'payload' => data })
50
+ end
51
+ end
52
+ end
53
+
54
+ # Copyright (c) 2022, Patrick W.
55
+ # All rights reserved.
56
+ #
57
+ # Redistribution and use in source and binary forms, with or without
58
+ # modification, are permitted provided that the following conditions are met:
59
+ #
60
+ # * Redistributions of source code must retain the above copyright notice, this
61
+ # list of conditions and the following disclaimer.
62
+ #
63
+ # * Redistributions in binary form must reproduce the above copyright notice,
64
+ # this list of conditions and the following disclaimer in the documentation
65
+ # and/or other materials provided with the distribution.
66
+ #
67
+ # * Neither the name of the copyright holder nor the names of its
68
+ # contributors may be used to endorse or promote products derived from
69
+ # this software without specific prior written permission.
70
+ #
71
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
72
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
74
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
75
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
76
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
77
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
78
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
79
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
81
+
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A module to provide publishing functions to an Object.
4
+ module RMessage::Publisher
5
+ # @!attribute [r] channel
6
+ # @return [String, Integer, Symbol] the channel to publish to
7
+ attr :channel
8
+
9
+ # Publishes a message to the specified redis channel.
10
+ # @param message [RMessage::Message] the message
11
+ # @param channel [String, Integer, Symbol] the channel
12
+ # @param connection_index [Integer] the index of the connection to Redis within the {RMessage::CONNECTION_POOL}
13
+ def publish(message, channel: @channel, connection_index: 0)
14
+ RMessage::CONNECTION_POOL[connection_index].publish(channel, message.build)
15
+ end
16
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Utility functions to allow setting up and parsing messages received from Redis publishers.
4
+ module RMessage::Subscriber
5
+ # @!attribute [r] channel
6
+ # @return [String, Symbol, Integer] the channel to subscribe to
7
+ attr :channel
8
+
9
+ # @!attribute [r] events
10
+ # @return [Hash] a map of event labels to classes
11
+ attr :events
12
+
13
+ # Setup a subscription to a specific Redis channel
14
+ # @param channel [Symbol, String, Integer] the channel
15
+ # @param auto_parse [Boolean] should messages be parsed automatically?
16
+ # @param connection_index [Integer] the index of the redis connection in {RMessage::CONNECTION_POOL}
17
+ def setup_subscription(channel: @channel, auto_parse: false, connection_index: 0, &_)
18
+ RMessage::CONNECTION_POOL[connection_index].subscribe(channel) do |event|
19
+ event.subscribe do
20
+ puts "Subscribed to #{channel}"
21
+ end
22
+
23
+ if auto_parse
24
+ event.message { |_, message| parse_message(message) }
25
+ else
26
+ event.message { |_, message| yield(message) }
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def parse_message(message_data)
34
+ msg = RMessage::Message.new(message_data)
35
+ msg.read
36
+ @events[msg.label].new(msg)
37
+ end
38
+ end
39
+
40
+ # Copyright (c) 2022, Patrick W.
41
+ # All rights reserved.
42
+ #
43
+ # Redistribution and use in source and binary forms, with or without
44
+ # modification, are permitted provided that the following conditions are met:
45
+ #
46
+ # * Redistributions of source code must retain the above copyright notice, this
47
+ # list of conditions and the following disclaimer.
48
+ #
49
+ # * Redistributions in binary form must reproduce the above copyright notice,
50
+ # this list of conditions and the following disclaimer in the documentation
51
+ # and/or other materials provided with the distribution.
52
+ #
53
+ # * Neither the name of the copyright holder nor the names of its
54
+ # contributors may be used to endorse or promote products derived from
55
+ # this software without specific prior written permission.
56
+ #
57
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
58
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
60
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
61
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
63
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
64
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
65
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
66
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/lib/rmessage.rb ADDED
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.dirname(__FILE__)].each { |file| $LOAD_PATH.unshift(file) if File.directory? file }
4
+
5
+ require 'druuid'
6
+ require 'dotenv'
7
+ require 'redis'
8
+ require 'oj'
9
+
10
+ # Utility modules to make it easier to build Pub/Sub systems in Ruby using Redis.
11
+ module RMessage
12
+ # @!attribute [r] CONNECTION_POOL
13
+ # @return [Array] a pool of connections
14
+ CONNECTION_POOL = []
15
+
16
+ autoload :Broker, 'rmessage/broker'
17
+ autoload :Publisher, 'rmessage/publisher'
18
+ autoload :Subscriber, 'rmessage/subscriber'
19
+ autoload :Message, 'rmessage/message'
20
+
21
+ def self.add_connection(opts = {})
22
+ CONNECTION_POOL << Redis.new(host: opts[:host], port: opts[:port])
23
+ end
24
+
25
+ def self.load_defaults
26
+ # Load ENV vars.
27
+ Dotenv.load('.env') if File.exist?('.env')
28
+ Oj.default_options = { mode: :object, cache_keys: true, cache_strings: true, symbol_keys: false }
29
+ RMessage.add_connection(host: ENV['RMESSAGE_REDIS_HOST'], port: ENV['RMESSAGE_REDIS_PORT'])
30
+ end
31
+ end
32
+
33
+ # Copyright (c) 2022, Patrick W.
34
+ # All rights reserved.
35
+ #
36
+ # Redistribution and use in source and binary forms, with or without
37
+ # modification, are permitted provided that the following conditions are met:
38
+ #
39
+ # * Redistributions of source code must retain the above copyright notice, this
40
+ # list of conditions and the following disclaimer.
41
+ #
42
+ # * Redistributions in binary form must reproduce the above copyright notice,
43
+ # this list of conditions and the following disclaimer in the documentation
44
+ # and/or other materials provided with the distribution.
45
+ #
46
+ # * Neither the name of the copyright holder nor the names of its
47
+ # contributors may be used to endorse or promote products derived from
48
+ # this software without specific prior written permission.
49
+ #
50
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
51
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
54
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
56
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
57
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
58
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rmessage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Patrick W.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dotenv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.7.6
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.7'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.7.6
33
+ - !ruby/object:Gem::Dependency
34
+ name: druuid
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.0.2
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.0.2
53
+ - !ruby/object:Gem::Dependency
54
+ name: oj
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.13'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.13.11
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.13'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.13.11
73
+ - !ruby/object:Gem::Dependency
74
+ name: redis
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '4.6'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 4.6.0
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '4.6'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 4.6.0
93
+ description:
94
+ email: Sickday@pm.me
95
+ executables: []
96
+ extensions: []
97
+ extra_rdoc_files: []
98
+ files:
99
+ - lib/rmessage.rb
100
+ - lib/rmessage/message.rb
101
+ - lib/rmessage/publisher.rb
102
+ - lib/rmessage/subscriber.rb
103
+ homepage: https://git.repos.pw/Sickday/rmessage
104
+ licenses:
105
+ - BSD-3-Clause
106
+ metadata:
107
+ source_code_uri: https://git.repos.pw/Sickday/rmessage
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.3.3
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Utility modules to make it easier to build Pub/Sub systems in Ruby using
127
+ Redis.
128
+ test_files: []