rflow 1.3.0 → 1.3.1
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/.gitignore +2 -0
- data/.yardopts +1 -1
- data/Vagrantfile +14 -10
- data/lib/rflow.rb +16 -1
- data/lib/rflow/broker.rb +6 -2
- data/lib/rflow/child_process.rb +23 -3
- data/lib/rflow/component.rb +68 -18
- data/lib/rflow/component/port.rb +111 -14
- data/lib/rflow/components/clock.rb +51 -0
- data/lib/rflow/components/integer.rb +40 -2
- data/lib/rflow/components/log.rb +39 -0
- data/lib/rflow/components/raw.rb +27 -0
- data/lib/rflow/components/replicate.rb +19 -0
- data/lib/rflow/components/ruby_proc_filter.rb +24 -0
- data/lib/rflow/configuration.rb +63 -25
- data/lib/rflow/configuration/component.rb +15 -0
- data/lib/rflow/configuration/connection.rb +39 -8
- data/lib/rflow/configuration/port.rb +20 -1
- data/lib/rflow/configuration/setting.rb +6 -0
- data/lib/rflow/configuration/shard.rb +7 -1
- data/lib/rflow/configuration/uuid_keyed.rb +5 -0
- data/lib/rflow/connection.rb +46 -11
- data/lib/rflow/connections/zmq_connection.rb +18 -1
- data/lib/rflow/daemon_process.rb +25 -0
- data/lib/rflow/logger.rb +29 -0
- data/lib/rflow/master.rb +15 -0
- data/lib/rflow/message.rb +69 -12
- data/lib/rflow/pid_file.rb +13 -2
- data/lib/rflow/shard.rb +37 -6
- data/lib/rflow/version.rb +2 -1
- metadata +2 -2
@@ -3,14 +3,29 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
+
# Represents a component definition in the SQLite database.
|
6
7
|
class Component < ConfigurationItem
|
7
8
|
include UUIDKeyed
|
8
9
|
include ActiveModel::Validations
|
9
10
|
|
11
|
+
# @!attribute options
|
12
|
+
# Open-ended Hash of component options, serialized via YAML to a single column.
|
13
|
+
# @return [Hash]
|
10
14
|
serialize :options, Hash
|
11
15
|
|
16
|
+
# @!attribute shard
|
17
|
+
# The {Shard} in which this {Component} is to run.
|
18
|
+
# @return [Shard]
|
12
19
|
belongs_to :shard, :primary_key => 'uuid', :foreign_key => 'shard_uuid'
|
20
|
+
|
21
|
+
# @!attribute input_ports
|
22
|
+
# The {InputPort}s of this component.
|
23
|
+
# @return [Array<InputPort>]
|
13
24
|
has_many :input_ports, :primary_key => 'uuid', :foreign_key => 'component_uuid'
|
25
|
+
|
26
|
+
# @!attribute output_ports
|
27
|
+
# The {OutputPort}s of this component.
|
28
|
+
# @return [Array<OutputPort>]
|
14
29
|
has_many :output_ports, :primary_key => 'uuid', :foreign_key => 'component_uuid'
|
15
30
|
|
16
31
|
#TODO: Get this to work
|
@@ -3,15 +3,27 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
+
# Represents a component-to-component connection in the SQLite database.
|
6
7
|
class Connection < ConfigurationItem
|
8
|
+
# Exception for when the connection is invalid.
|
7
9
|
class ConnectionInvalid < StandardError; end
|
8
10
|
|
9
11
|
include UUIDKeyed
|
10
12
|
include ActiveModel::Validations
|
11
13
|
|
14
|
+
# @!attribute options
|
15
|
+
# Open-ended Hash of component options, serialized via YAML to a single column.
|
16
|
+
# @return [Hash]
|
12
17
|
serialize :options, Hash
|
13
18
|
|
19
|
+
# @!attribute input_port
|
20
|
+
# The {InputPort} to which this {Connection} delivers messages.
|
21
|
+
# @return [InputPort]
|
14
22
|
belongs_to :input_port, :primary_key => 'uuid', :foreign_key => 'input_port_uuid'
|
23
|
+
|
24
|
+
# @!attribute output_port
|
25
|
+
# The {OutputPort} from which this {Connection} receives messages.
|
26
|
+
# @return [OutputPort]
|
15
27
|
belongs_to :output_port,:primary_key => 'uuid', :foreign_key => 'output_port_uuid'
|
16
28
|
|
17
29
|
before_create :merge_default_options!
|
@@ -21,6 +33,7 @@ class RFlow
|
|
21
33
|
|
22
34
|
validate :all_required_options_present?
|
23
35
|
|
36
|
+
# @!visibility private
|
24
37
|
def all_required_options_present?
|
25
38
|
self.class.required_options.each do |option_name|
|
26
39
|
unless self.options.include? option_name.to_s
|
@@ -29,6 +42,7 @@ class RFlow
|
|
29
42
|
end
|
30
43
|
end
|
31
44
|
|
45
|
+
# @!visibility private
|
32
46
|
def merge_default_options!
|
33
47
|
self.options ||= {}
|
34
48
|
self.class.default_options.each do |name, default_value_or_proc|
|
@@ -37,22 +51,29 @@ class RFlow
|
|
37
51
|
end
|
38
52
|
|
39
53
|
# Should return a list of require option names which will be
|
40
|
-
# used in validations.
|
54
|
+
# used in validations. To be overridden by subclasses.
|
55
|
+
# @return [Array<String>]
|
41
56
|
def self.required_options; []; end
|
42
57
|
|
43
58
|
# Should return a hash of default options, where the keys are
|
44
59
|
# the option names and the values are either default option
|
45
60
|
# values or Procs that take a single connection argument. This
|
46
61
|
# allow defaults to use other parameters in the connection to
|
47
|
-
# construct the appropriate default value.
|
62
|
+
# construct the appropriate default value. To be overridden
|
63
|
+
# by subclasses.
|
64
|
+
# @return [Hash]
|
48
65
|
def self.default_options; {}; end
|
49
66
|
|
50
67
|
# By default, no broker processes are required to manage a connection.
|
68
|
+
# To be overridden by subclasses.
|
69
|
+
# @return [Array<Broker>]
|
51
70
|
def brokers; []; end
|
52
71
|
end
|
53
72
|
|
54
|
-
#
|
73
|
+
# Subclass of {Connection} for ZMQ connections and their required options.
|
55
74
|
class ZMQConnection < Connection
|
75
|
+
# Default options required for ZeroMQ connection.
|
76
|
+
# @return [Hash]
|
56
77
|
def self.default_options
|
57
78
|
{
|
58
79
|
'output_socket_type' => 'PUSH',
|
@@ -65,15 +86,16 @@ class RFlow
|
|
65
86
|
end
|
66
87
|
end
|
67
88
|
|
68
|
-
#
|
89
|
+
# Subclass of {Connection} for brokered ZMQ connections and their required options.
|
69
90
|
#
|
70
91
|
# We name the IPCs to resemble a quasi-component. Outputting to this
|
71
|
-
# connection goes to the
|
72
|
-
# connection comes from the
|
92
|
+
# connection goes to the +in+ of the IPC pair. Reading input from this
|
93
|
+
# connection comes from the +out+ of the IPC pair.
|
73
94
|
#
|
74
95
|
# The broker shuttles messages between the two to support the many-to-many
|
75
96
|
# delivery pattern.
|
76
97
|
class BrokeredZMQConnection < Connection
|
98
|
+
# Default ZeroMQ options required for broker connection.
|
77
99
|
def self.default_options
|
78
100
|
{
|
79
101
|
'output_socket_type' => 'PUSH',
|
@@ -86,6 +108,7 @@ class RFlow
|
|
86
108
|
end
|
87
109
|
|
88
110
|
# A brokered ZMQ connection requires one broker process.
|
111
|
+
# @return [Array<Broker>]
|
89
112
|
def brokers
|
90
113
|
@brokers ||= [ZMQStreamer.new(self)]
|
91
114
|
end
|
@@ -95,6 +118,8 @@ class RFlow
|
|
95
118
|
# that can't be derived from the connection. Not persisted in the database -
|
96
119
|
# it's encapsulated in the nature of the connection.
|
97
120
|
class ZMQStreamer
|
121
|
+
# Backreference to the {Connection}.
|
122
|
+
# @return [Connection]
|
98
123
|
attr_reader :connection
|
99
124
|
|
100
125
|
def initialize(connection)
|
@@ -102,9 +127,15 @@ class RFlow
|
|
102
127
|
end
|
103
128
|
end
|
104
129
|
|
105
|
-
#
|
130
|
+
# For testing purposes only.
|
131
|
+
# @!visibility private
|
106
132
|
class NullConnectionConfiguration
|
107
|
-
attr_accessor :name
|
133
|
+
attr_accessor :name
|
134
|
+
attr_accessor :uuid
|
135
|
+
attr_accessor :options
|
136
|
+
attr_accessor :input_port_key
|
137
|
+
attr_accessor :output_port_key
|
138
|
+
attr_accessor :delivery
|
108
139
|
end
|
109
140
|
end
|
110
141
|
end
|
@@ -3,24 +3,43 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
+
# Represents a component port in the SQLite database.
|
6
7
|
class Port < ConfigurationItem
|
7
8
|
include UUIDKeyed
|
8
9
|
include ActiveModel::Validations
|
9
10
|
|
11
|
+
# @!attribute component
|
12
|
+
# The {Component} to which this port belongs.
|
13
|
+
# @return [Component]
|
10
14
|
belongs_to :component, :primary_key => 'uuid', :foreign_key => 'component_uuid'
|
11
15
|
|
12
16
|
# TODO: Make some sort of component/port validation work here
|
13
17
|
#validate :component_has_defined_port
|
14
18
|
end
|
15
19
|
|
16
|
-
#
|
20
|
+
# Subclass of {Port} to represent input ports.
|
17
21
|
class InputPort < Port
|
22
|
+
# @!attribute input_connections
|
23
|
+
# The connections delivering messages to this {InputPort}.
|
24
|
+
# @return [Array<Connection>]
|
18
25
|
has_many :input_connections, :class_name => 'RFlow::Configuration::Connection', :primary_key => 'uuid', :foreign_key => 'input_port_uuid'
|
26
|
+
|
27
|
+
# @!attribute connections
|
28
|
+
# Synonym for {input_connections}.
|
29
|
+
# @return [Array<Connection>]
|
19
30
|
has_many :connections, :class_name => 'RFlow::Configuration::Connection', :primary_key => 'uuid', :foreign_key => 'input_port_uuid'
|
20
31
|
end
|
21
32
|
|
33
|
+
# Subclass of {Port} to represent output ports.
|
22
34
|
class OutputPort < Port
|
35
|
+
# @!attribute output_connections
|
36
|
+
# The connections receiving messages from this {OutputPort}.
|
37
|
+
# @return [Array<Connection>]
|
23
38
|
has_many :output_connections, :class_name => 'RFlow::Configuration::Connection', :primary_key => 'uuid', :foreign_key => 'output_port_uuid'
|
39
|
+
|
40
|
+
# @!attribute connections
|
41
|
+
# Synonym for {output_connections}.
|
42
|
+
# @return [Array<Connection>]
|
24
43
|
has_many :connections, :class_name => 'RFlow::Configuration::Connection', :primary_key => 'uuid', :foreign_key => 'output_port_uuid'
|
25
44
|
end
|
26
45
|
end
|
@@ -3,11 +3,13 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
+
# Represents a setting in the SQLite database.
|
6
7
|
class Setting < ConfigurationItem
|
7
8
|
include ActiveModel::Validations
|
8
9
|
|
9
10
|
self.primary_key = 'name'
|
10
11
|
|
12
|
+
# Default settings.
|
11
13
|
DEFAULTS = {
|
12
14
|
'rflow.application_name' => 'rflow',
|
13
15
|
'rflow.application_directory_path' => '.',
|
@@ -18,6 +20,7 @@ class RFlow
|
|
18
20
|
'rflow.log_level' => 'INFO',
|
19
21
|
}
|
20
22
|
|
23
|
+
private
|
21
24
|
DIRECTORY_PATHS = [
|
22
25
|
'rflow.application_directory_path',
|
23
26
|
'rflow.pid_directory_path',
|
@@ -52,6 +55,9 @@ class RFlow
|
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
58
|
+
public
|
59
|
+
# Look up a {Setting} by name from the SQLite database.
|
60
|
+
# @return [Setting]
|
55
61
|
def self.[](name)
|
56
62
|
Setting.find(name).value rescue nil
|
57
63
|
end
|
@@ -3,20 +3,26 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
+
# Represents a process shard in the SQLite database.
|
6
7
|
class Shard < ConfigurationItem
|
7
8
|
include UUIDKeyed
|
8
9
|
include ActiveModel::Validations
|
9
10
|
|
11
|
+
# Exception for when the shard is invalid.
|
10
12
|
class ShardInvalid < StandardError; end
|
11
13
|
|
14
|
+
# @!attribute components
|
15
|
+
# The {Component}s that are to run in this {Shard}.
|
16
|
+
# @return [Array<Component>]
|
12
17
|
has_many :components, :primary_key => 'uuid', :foreign_key => 'shard_uuid'
|
13
18
|
|
14
19
|
validates_uniqueness_of :name
|
15
20
|
validates_numericality_of :count, :only_integer => true, :greater_than => 0
|
16
21
|
end
|
17
22
|
|
18
|
-
#
|
23
|
+
# Subclass of {Shard} representing a shard instantiated by a process.
|
19
24
|
class ProcessShard < Shard; end
|
25
|
+
# Subclass of {Shard} representing a shard instantiated by a thread.
|
20
26
|
class ThreadShard < Shard; end
|
21
27
|
end
|
22
28
|
end
|
@@ -2,7 +2,12 @@ require 'uuidtools'
|
|
2
2
|
|
3
3
|
class RFlow
|
4
4
|
class Configuration
|
5
|
+
# Mixin for any {ConfigurationItem} that has a UUID key.
|
6
|
+
# Sets +primary_key+ column to be +uuid+ and initializes the
|
7
|
+
# UUID on creation.
|
8
|
+
# @!visibility private
|
5
9
|
module UUIDKeyed
|
10
|
+
# @!visibility private
|
6
11
|
def self.included(base)
|
7
12
|
base.class_eval do
|
8
13
|
self.primary_key = 'uuid'
|
data/lib/rflow/connection.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'rflow/message'
|
2
2
|
|
3
3
|
class RFlow
|
4
|
+
# Represents an RFlow connection from one component to another.
|
4
5
|
class Connection
|
5
6
|
class << self
|
7
|
+
# Build an appropriate subclass of {Connection} based on the configuration.
|
8
|
+
# @return [Connection]
|
6
9
|
def build(config)
|
7
10
|
case config.type
|
8
11
|
when 'RFlow::Configuration::ZMQConnection'
|
@@ -15,7 +18,22 @@ class RFlow
|
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
18
|
-
|
21
|
+
# The reference to the connection's configuration.
|
22
|
+
# @return [Configuration::Connection]
|
23
|
+
attr_accessor :config
|
24
|
+
|
25
|
+
# The connection's UUID.
|
26
|
+
# @return [String]
|
27
|
+
attr_accessor :uuid
|
28
|
+
|
29
|
+
# The connection's name.
|
30
|
+
# @return [String]
|
31
|
+
attr_accessor :name
|
32
|
+
|
33
|
+
# The connection's options Hash.
|
34
|
+
# @return [Hash]
|
35
|
+
attr_accessor :options
|
36
|
+
|
19
37
|
attr_writer :recv_callback
|
20
38
|
protected
|
21
39
|
attr_reader :recv_callback
|
@@ -28,44 +46,55 @@ class RFlow
|
|
28
46
|
@options = config.options
|
29
47
|
end
|
30
48
|
|
31
|
-
# Subclass and implement to be able to handle future
|
49
|
+
# Subclass and implement to be able to handle future +recv+
|
32
50
|
# methods. Will only be called in the context of a running
|
33
|
-
# EventMachine reactor
|
51
|
+
# EventMachine reactor.
|
52
|
+
# @return [void]
|
34
53
|
def connect_input!
|
35
54
|
raise NotImplementedError, 'Raw connections do not support connect_input. Please subclass and define a connect_input method.'
|
36
55
|
end
|
37
56
|
|
38
|
-
# Subclass and implement to be able to handle future
|
57
|
+
# Subclass and implement to be able to handle future +send+
|
39
58
|
# methods. Will only be called in the context of a running
|
40
|
-
# EventMachine reactor
|
59
|
+
# EventMachine reactor.
|
60
|
+
# @return [void]
|
41
61
|
def connect_output!
|
42
62
|
raise NotImplementedError, 'Raw connections do not support connect_output. Please subclass and define a connect_output method.'
|
43
63
|
end
|
44
64
|
|
45
65
|
# Subclass and implement to handle outgoing messages. The message
|
46
|
-
# will be a RFlow::Message object and the subclasses are expected
|
66
|
+
# will be a {RFlow::Message} object and the subclasses are expected
|
47
67
|
# to marshal it up into something that will be unmarshalled on the
|
48
|
-
# other side
|
68
|
+
# other side.
|
69
|
+
# @return [void]
|
49
70
|
def send_message(message)
|
50
71
|
raise NotImplementedError, 'Raw connections do not support send_message. Please subclass and define a send_message method.'
|
51
72
|
end
|
52
73
|
|
53
74
|
# Parent component will set this attribute if it expects to
|
54
|
-
#
|
55
|
-
# (recv_callback.call(message)) when it gets a new message, which
|
75
|
+
# receive messages. {Connection} subclass should call it
|
76
|
+
# (<tt>recv_callback.call(message)</tt>) when it gets a new message, which
|
56
77
|
# will be transmitted back to the parent component's
|
57
|
-
# process_message method.
|
58
|
-
# deserializing whatever was on the wire into a RFlow::Message object
|
78
|
+
# {Component#process_message} method. Subclass is responsible for
|
79
|
+
# deserializing whatever was on the wire into a {RFlow::Message} object.
|
80
|
+
# @return [Proc]
|
59
81
|
def recv_callback
|
60
82
|
@recv_callback ||= Proc.new {|message|}
|
61
83
|
end
|
62
84
|
|
85
|
+
# If we are connected to an {Component::InputPort} subport, the key for that subport.
|
86
|
+
# @return [String]
|
63
87
|
def input_port_key; config.input_port_key; end
|
88
|
+
|
89
|
+
# If we are connected to an {Component::OutputPort} subport, the key for that subport.
|
90
|
+
# @return [String]
|
64
91
|
def output_port_key; config.output_port_key; end
|
65
92
|
end
|
66
93
|
|
67
94
|
# Primarily for testing purposes. Captures whatever messages are sent on it.
|
68
95
|
class MessageCollectingConnection < Connection
|
96
|
+
# The messages that were collected.
|
97
|
+
# @return [Array<RFlow::Message>]
|
69
98
|
attr_accessor :messages
|
70
99
|
|
71
100
|
def initialize
|
@@ -73,6 +102,8 @@ class RFlow
|
|
73
102
|
@messages = []
|
74
103
|
end
|
75
104
|
|
105
|
+
# Override of {send_message} which adds the message to {messages}.
|
106
|
+
# @return [void]
|
76
107
|
def send_message(message)
|
77
108
|
@messages << message
|
78
109
|
end
|
@@ -88,6 +119,8 @@ class RFlow
|
|
88
119
|
@target_port = target_port
|
89
120
|
end
|
90
121
|
|
122
|
+
# Override of {send_message} which forwards the message to the target port.
|
123
|
+
# @return [void]
|
91
124
|
def send_message(message)
|
92
125
|
@target_port.send_message(message)
|
93
126
|
end
|
@@ -104,6 +137,8 @@ class RFlow
|
|
104
137
|
@target_port = target_port
|
105
138
|
end
|
106
139
|
|
140
|
+
# Override of {send_message} which forwards the message to the target port.
|
141
|
+
# @return [void]
|
107
142
|
def send_message(message)
|
108
143
|
@receiver.process_message(@target_port, nil, self, message)
|
109
144
|
end
|
@@ -9,11 +9,16 @@ require 'rflow/broker'
|
|
9
9
|
require 'sys/filesystem'
|
10
10
|
|
11
11
|
class RFlow
|
12
|
+
# Contains all connections classes.
|
12
13
|
module Connections
|
14
|
+
# Represents a ZeroMQ connection.
|
13
15
|
class ZMQConnection < RFlow::Connection
|
14
16
|
class << self
|
17
|
+
# The ZeroMQ context object.
|
18
|
+
# @return [EM::ZeroMQ::Context]
|
15
19
|
attr_accessor :zmq_context
|
16
20
|
|
21
|
+
# @!visibility private
|
17
22
|
def create_zmq_context
|
18
23
|
version = LibZMQ::version
|
19
24
|
RFlow.logger.debug { "Creating a new ZeroMQ context; ZeroMQ version is #{version[:major]}.#{version[:minor]}.#{version[:patch]}" }
|
@@ -23,12 +28,13 @@ class RFlow
|
|
23
28
|
EM::ZeroMQ::Context.new(1)
|
24
29
|
end
|
25
30
|
|
26
|
-
# Returns the current ZeroMQ context object or creates it if it does not exist.
|
27
31
|
def zmq_context
|
28
32
|
@zmq_context ||= create_zmq_context
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
36
|
+
# The ZeroMQ context object.
|
37
|
+
# @return [EM::ZeroMQ::Context]
|
32
38
|
def zmq_context; ZMQConnection.zmq_context; end
|
33
39
|
|
34
40
|
private
|
@@ -41,6 +47,8 @@ class RFlow
|
|
41
47
|
zmq_context # cause the ZMQ context to be created before the reactor is running
|
42
48
|
end
|
43
49
|
|
50
|
+
# Hook up the input to the real ZeroMQ sockets.
|
51
|
+
# @return [void]
|
44
52
|
def connect_input!
|
45
53
|
RFlow.logger.debug "Connecting input #{uuid} with #{options.find_all {|k, v| k.to_s =~ /input/}}"
|
46
54
|
check_address(options['input_address'])
|
@@ -65,6 +73,8 @@ class RFlow
|
|
65
73
|
input_socket
|
66
74
|
end
|
67
75
|
|
76
|
+
# Hook up the output to the real ZeroMQ sockets.
|
77
|
+
# @return [void]
|
68
78
|
def connect_output!
|
69
79
|
RFlow.logger.debug "Connecting output #{uuid} with #{options.find_all {|k, v| k.to_s =~ /output/}}"
|
70
80
|
check_address(options['output_address'])
|
@@ -74,6 +84,8 @@ class RFlow
|
|
74
84
|
output_socket
|
75
85
|
end
|
76
86
|
|
87
|
+
# Send a message along the connection into ZeroMQ.
|
88
|
+
# @return [void]
|
77
89
|
def send_message(message)
|
78
90
|
RFlow.logger.debug "#{name}: Sending message of type '#{message.data_type_name.to_s}'"
|
79
91
|
|
@@ -123,6 +135,9 @@ class RFlow
|
|
123
135
|
end
|
124
136
|
end
|
125
137
|
|
138
|
+
# Subclass of {ZMQConnection} representing a brokered ZeroMQ connection
|
139
|
+
# (one where messages are sent to a separate process performing the
|
140
|
+
# many-to-many brokering function).
|
126
141
|
class BrokeredZMQConnection < ZMQConnection
|
127
142
|
end
|
128
143
|
|
@@ -139,6 +154,8 @@ class RFlow
|
|
139
154
|
super("broker-#{connection.name}", 'Broker')
|
140
155
|
end
|
141
156
|
|
157
|
+
# Start the broker process. Returns when things are shutting down.
|
158
|
+
# @return [void]
|
142
159
|
def run_process
|
143
160
|
version = LibZMQ::version
|
144
161
|
RFlow.logger.debug { "Creating a new ZeroMQ context; ZeroMQ version is #{version[:major]}.#{version[:minor]}.#{version[:patch]}" }
|