litestack 0.4.2 → 0.4.4

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.standard.yml +3 -1
  3. data/BENCHMARKS.md +3 -3
  4. data/CAVEATS.md +20 -0
  5. data/CHANGELOG.md +40 -1
  6. data/FILESYSTEMS.md +55 -0
  7. data/Gemfile +2 -0
  8. data/README.md +8 -4
  9. data/ROADMAP.md +6 -6
  10. data/assets/litestack_advantage.png +0 -0
  11. data/bench/bench.rb +2 -0
  12. data/bench/bench_cache_rails.rb +33 -2
  13. data/bench/bench_cache_raw.rb +36 -12
  14. data/bench/bench_jobs_rails.rb +3 -3
  15. data/bench/bench_jobs_raw.rb +3 -3
  16. data/bin/liteboard +16 -13
  17. data/gemfiles/rails70.gemfile +5 -0
  18. data/gemfiles/rails71.gemfile +5 -0
  19. data/gemfiles/rails71.gemfile.lock +264 -0
  20. data/lib/active_job/queue_adapters/litejob_adapter.rb +11 -3
  21. data/lib/active_record/connection_adapters/litedb_adapter.rb +8 -0
  22. data/lib/active_support/cache/litecache.rb +40 -7
  23. data/lib/generators/litestack/install/install_generator.rb +2 -2
  24. data/lib/generators/litestack/install/templates/cable.yml +0 -3
  25. data/lib/litestack/liteboard/liteboard.rb +15 -19
  26. data/lib/litestack/liteboard/views/litecable.erb +1 -1
  27. data/lib/litestack/litecable.rb +1 -1
  28. data/lib/litestack/litecache.rb +51 -19
  29. data/lib/litestack/litecache.sql.yml +7 -5
  30. data/lib/litestack/litedb.rb +5 -1
  31. data/lib/litestack/litejob.rb +1 -1
  32. data/lib/litestack/litejobqueue.rb +24 -14
  33. data/lib/litestack/litemetric.rb +7 -6
  34. data/lib/litestack/litemetric.sql.yml +1 -1
  35. data/lib/litestack/litemetric_collector.sql.yml +1 -1
  36. data/lib/litestack/litequeue.rb +17 -2
  37. data/lib/litestack/litequeue.sql.yml +38 -5
  38. data/lib/litestack/litescheduler.rb +9 -4
  39. data/lib/litestack/litesearch/index.rb +11 -10
  40. data/lib/litestack/litesearch/model.rb +61 -3
  41. data/lib/litestack/litesearch/schema.rb +7 -2
  42. data/lib/litestack/litesearch/schema_adapters/backed_adapter.rb +69 -25
  43. data/lib/litestack/litesearch/schema_adapters.rb +4 -4
  44. data/lib/litestack/litesearch.rb +2 -2
  45. data/lib/litestack/litesupport.rb +9 -7
  46. data/lib/litestack/railtie.rb +4 -2
  47. data/lib/litestack/version.rb +1 -1
  48. data/lib/litestack.rb +15 -15
  49. data/lib/railties/rails/commands/dbconsole.rb +5 -5
  50. data/lib/sequel/adapters/litedb.rb +9 -1
  51. data/lib/sequel/adapters/shared/litedb.rb +2 -2
  52. data/scripts/build_metrics.rb +2 -2
  53. data/scripts/test_cable.rb +1 -1
  54. metadata +105 -56
  55. data/Gemfile.lock +0 -92
@@ -25,20 +25,24 @@ class Litesearch::Schema::BackedAdapter < Litesearch::Schema::ContentlessAdapter
25
25
 
26
26
  def create_primary_triggers_sql(active = false)
27
27
  when_stmt = "TRUE"
28
- cols = active_cols_names
28
+ cols = active_cols_names.select{|n| !n.nil?}
29
29
  if (filter = @schema[:filter_column])
30
30
  when_stmt = "NEW.#{filter} = TRUE"
31
31
  cols << filter
32
32
  end
33
+ update_filter = ""
34
+ if cols.length > 0
35
+ " OF #{cols.join(', ')} "
36
+ end
33
37
 
34
38
  <<-SQL
35
39
  CREATE TRIGGER #{name}_insert AFTER INSERT ON #{table} WHEN #{when_stmt} BEGIN
36
40
  INSERT OR REPLACE INTO #{name}(rowid, #{active_field_names.join(", ")}) VALUES (NEW.rowid, #{trigger_cols_sql});
37
41
  END;
38
- CREATE TRIGGER #{name}_update AFTER UPDATE OF #{cols.join(", ")} ON #{table} WHEN #{when_stmt} BEGIN
42
+ CREATE TRIGGER #{name}_update AFTER UPDATE #{update_filter} ON #{table} WHEN #{when_stmt} BEGIN
39
43
  INSERT OR REPLACE INTO #{name}(rowid, #{active_field_names.join(", ")}) VALUES (NEW.rowid, #{trigger_cols_sql});
40
44
  END;
41
- CREATE TRIGGER #{name}_update_not AFTER UPDATE OF #{cols.join(", ")} ON #{table} WHEN NOT #{when_stmt} BEGIN
45
+ CREATE TRIGGER #{name}_update_not AFTER UPDATE #{update_filter} ON #{table} WHEN NOT #{when_stmt} BEGIN
42
46
  DELETE FROM #{name} WHERE rowid = NEW.rowid;
43
47
  END;
44
48
  CREATE TRIGGER #{name}_delete AFTER DELETE ON #{table} BEGIN
@@ -51,19 +55,41 @@ class Litesearch::Schema::BackedAdapter < Litesearch::Schema::ContentlessAdapter
51
55
  "DROP TRIGGER IF EXISTS #{target_table}_#{target_col}_#{col}_#{name}_update;"
52
56
  end
53
57
 
58
+ def drop_secondary_trigger_poly_sql(target_table, target_col, col)
59
+ "DROP TRIGGER IF EXISTS #{target_table}_#{target_col}_#{name}_update;"
60
+ end
61
+
54
62
  def create_secondary_trigger_sql(target_table, target_col, col)
55
63
  <<~SQL
56
- CREATE TRIGGER #{target_table}_#{target_col}_#{col}_#{name}_update AFTER UPDATE OF #{target_col} ON #{target_table} BEGIN
64
+ CREATE TRIGGER IF NOT EXISTS #{target_table}_#{target_col}_#{col}_#{name}_update AFTER UPDATE OF #{target_col} ON #{target_table} BEGIN
57
65
  #{rebuild_sql} AND #{table}.#{col} = NEW.id;
58
66
  END;
59
67
  SQL
60
68
  end
61
69
 
70
+ def create_secondary_trigger_poly_sql(target_table, target_col, col, conditions)
71
+ conditions_sql = conditions.collect{|k, v| "NEW.#{k} = '#{v}'"}.join(" AND ")
72
+ <<~SQL
73
+ CREATE TRIGGER IF NOT EXISTS #{target_table}_#{target_col}_#{name}_insert AFTER INSERT ON #{target_table} WHEN #{conditions_sql} BEGIN
74
+ #{rebuild_sql};
75
+ END;
76
+ CREATE TRIGGER IF NOT EXISTS #{target_table}_#{target_col}_#{name}_update AFTER UPDATE ON #{target_table} WHEN #{conditions_sql} BEGIN
77
+ #{rebuild_sql};
78
+ END;
79
+ SQL
80
+ end
81
+
82
+
83
+
62
84
  def drop_secondary_triggers_sql
63
85
  sql = ""
64
86
  @schema[:fields].each do |name, field|
65
87
  if field[:trigger_sql]
66
- sql << drop_secondary_trigger_sql(field[:target_table], field[:target_col], field[:col])
88
+ if field[:col]
89
+ sql << drop_secondary_trigger_sql(field[:target_table], field[:target_col], field[:col])
90
+ elsif field[:source]
91
+ sql << drop_secondary_trigger_poly_sql(field[:target_table], field[:target_col], name)
92
+ end
67
93
  end
68
94
  end
69
95
  sql.empty? ? nil : sql
@@ -73,18 +99,18 @@ class Litesearch::Schema::BackedAdapter < Litesearch::Schema::ContentlessAdapter
73
99
  sql = ""
74
100
  @schema[:fields].each do |name, field|
75
101
  if field[:trigger_sql]
76
- sql << create_secondary_trigger_sql(field[:target_table], field[:target_col], field[:col])
102
+ if field[:col]
103
+ sql << create_secondary_trigger_sql(field[:target_table], field[:target_col], field[:col])
104
+ elsif field[:source]
105
+ sql << create_secondary_trigger_poly_sql(field[:target_table], field[:target_col], name, field[:conditions])
106
+ end
77
107
  end
78
108
  end
79
109
  sql.empty? ? nil : sql
80
110
  end
81
111
 
82
112
  def rebuild_sql
83
- conditions = ""
84
- jcs = join_conditions_sql
85
- fs = filter_sql
86
- conditions = " ON #{jcs} #{fs}" unless jcs.empty? && fs.empty?
87
- "INSERT OR REPLACE INTO #{name}(rowid, #{active_field_names.join(", ")}) SELECT #{table}.id, #{select_cols_sql} FROM #{join_tables_sql} #{conditions}"
113
+ "INSERT OR REPLACE INTO #{name}(rowid, #{active_field_names.join(", ")}) SELECT #{table}.id, #{select_cols_sql} FROM #{joins_sql} #{filter_sql}"
88
114
  end
89
115
 
90
116
  def enrich_schema
@@ -92,12 +118,23 @@ class Litesearch::Schema::BackedAdapter < Litesearch::Schema::ContentlessAdapter
92
118
  if field[:target] && !field[:target].start_with?("#{table}.")
93
119
  field[:target] = field[:target].downcase
94
120
  target_table, target_col = field[:target].split(".")
95
- field[:col] = "#{name}_id".to_sym unless field[:col]
121
+ field[:col] = :"#{name}_id" unless field[:col]
96
122
  field[:target_table] = target_table.to_sym
97
123
  field[:target_col] = target_col.to_sym
98
124
  field[:sql] = "(SELECT #{field[:target_col]} FROM #{field[:target_table]} WHERE id = NEW.#{field[:col]})"
99
125
  field[:trigger_sql] = true # create_secondary_trigger_sql(field[:target_table], field[:target_col], field[:col])
100
126
  field[:target_table_alias] = "#{field[:target_table]}_#{name}"
127
+ elsif field[:source]
128
+ field[:source] = field[:source].downcase
129
+ target_table, target_col = field[:source].split(".")
130
+ field[:target_table] = target_table.to_sym
131
+ field[:target_col] = target_col.to_sym
132
+ field[:conditions_sql] = field[:conditions].collect{|k, v| "#{k} = '#{v}'"}.join(" AND ") if field[:conditions]
133
+ field[:sql] = "SELECT #{field[:target_col]} FROM #{field[:target_table]} WHERE #{field[:reference]} = NEW.id"
134
+ field[:sql] += " AND #{field[:conditions_sql]}" if field[:conditions_sql]
135
+ field[:sql] = "(#{field[:sql]})"
136
+ field[:trigger_sql] = true
137
+ field[:target_table_alias] = "#{field[:target_table]}_#{name}"
101
138
  else
102
139
  field[:col] = name unless field[:col]
103
140
  field[:sql] = field[:col]
@@ -109,7 +146,7 @@ class Litesearch::Schema::BackedAdapter < Litesearch::Schema::ContentlessAdapter
109
146
 
110
147
  def filter_sql
111
148
  sql = ""
112
- sql << " AND #{@schema[:filter_column]} = TRUE " if @schema[:filter_column]
149
+ sql << " WHERE #{@schema[:filter_column]} = TRUE " if @schema[:filter_column]
113
150
  sql
114
151
  end
115
152
 
@@ -124,20 +161,27 @@ class Litesearch::Schema::BackedAdapter < Litesearch::Schema::ContentlessAdapter
124
161
  (!field[:trigger_sql].nil?) ? "#{field[:target_table_alias]}.#{field[:target_col]}" : field[:target]
125
162
  end.join(", ")
126
163
  end
127
-
128
- def join_tables_sql
129
- tables = [@schema[:table]]
164
+
165
+ def joins_sql
166
+ joins = [@schema[:table]]
130
167
  active_fields.each do |name, field|
131
- tables << "#{field[:target_table]} AS #{field[:target_table_alias]}" if field[:trigger_sql]
168
+ if field[:trigger_sql]
169
+ join_table = ""
170
+ join_table << "#{field[:target_table]} AS #{field[:target_table_alias]} ON "
171
+ if field[:col]
172
+ join_table << "#{field[:target_table_alias]}.id = #{@schema[:table]}.#{field[:col]}" if field[:col]
173
+ elsif field[:source]
174
+ join_table << "#{field[:target_table_alias]}.#{field[:reference]} = #{@schema[:table]}.id"
175
+ if field[:conditions]
176
+ join_table << " AND "
177
+ join_table << field[:conditions].collect{|k, v| "#{field[:target_table_alias]}.#{k} = '#{v}'"}.join(" AND ")
178
+ end
179
+ end
180
+ joins << join_table
181
+ end
132
182
  end
133
- tables.uniq.join(", ")
183
+ joins.join(" LEFT JOIN ")
134
184
  end
135
185
 
136
- def join_conditions_sql
137
- conditions = []
138
- active_fields.each do |name, field|
139
- conditions << "#{field[:target_table_alias]}.id = #{@schema[:table]}.#{field[:col]}" if field[:trigger_sql]
140
- end
141
- conditions.join(" AND ")
142
- end
186
+
143
187
  end
@@ -1,4 +1,4 @@
1
- require_relative "./schema_adapters/basic_adapter"
2
- require_relative "./schema_adapters/standalone_adapter"
3
- require_relative "./schema_adapters/contentless_adapter"
4
- require_relative "./schema_adapters/backed_adapter"
1
+ require_relative "schema_adapters/basic_adapter"
2
+ require_relative "schema_adapters/standalone_adapter"
3
+ require_relative "schema_adapters/contentless_adapter"
4
+ require_relative "schema_adapters/backed_adapter"
@@ -4,8 +4,8 @@ module Litesearch
4
4
  class Schema; end
5
5
  end
6
6
 
7
- require_relative "./litesearch/index"
8
- require_relative "./litesearch/model"
7
+ require_relative "litesearch/index"
8
+ require_relative "litesearch/model"
9
9
 
10
10
  module Litesearch
11
11
  def litesearch_index_cache
@@ -6,15 +6,16 @@ require "oj"
6
6
  require "yaml"
7
7
  require "pathname"
8
8
  require "fileutils"
9
+ require "erb"
9
10
 
10
- require_relative "./litescheduler"
11
+ require_relative "litescheduler"
11
12
 
12
13
  module Litesupport
13
14
  class Error < StandardError; end
14
15
 
15
16
  # Detect the Rack or Rails environment.
16
17
  def self.detect_environment
17
- if defined? Rails
18
+ if defined?(Rails) && Rails.respond_to?(:env)
18
19
  Rails.env
19
20
  elsif ENV["RACK_ENV"]
20
21
  ENV["RACK_ENV"]
@@ -174,7 +175,7 @@ module Litesupport
174
175
  end
175
176
 
176
177
  def configure(options = {})
177
- # detect enviornment (production, development, etc.)
178
+ # detect environment (production, development, etc.)
178
179
  defaults = begin
179
180
  self.class::DEFAULT_OPTIONS
180
181
  rescue
@@ -182,11 +183,11 @@ module Litesupport
182
183
  end
183
184
  @options = defaults.merge(options)
184
185
  config = begin
185
- YAML.load_file(@options[:config_path])
186
+ YAML.load(ERB.new(File.read(@options[:config_path])).result)
186
187
  rescue
187
188
  {}
188
189
  end # an empty hash won't hurt
189
- config = config[Litesupport.environment] if config[Litesupport.environment] # if there is a config for the current enviornment defined then use it, otherwise use the top level declaration
190
+ config = config[Litesupport.environment] if config[Litesupport.environment] # if there is a config for the current environment defined then use it, otherwise use the top level declaration
190
191
  config.keys.each do |k| # symbolize keys
191
192
  config[k.to_sym] = config[k]
192
193
  config.delete k
@@ -196,7 +197,7 @@ module Litesupport
196
197
  end
197
198
 
198
199
  def setup
199
- @conn = create_pooled_connection
200
+ @conn = create_pooled_connection(@options[:connection_count])
200
201
  @logger = create_logger
201
202
  @running = true
202
203
  end
@@ -231,7 +232,8 @@ module Litesupport
231
232
  end
232
233
 
233
234
  def create_pooled_connection(count = 1)
234
- Litesupport::Pool.new(1) { create_connection }
235
+ count = 1 unless count&.is_a?(Integer)
236
+ Litesupport::Pool.new(count) { create_connection }
235
237
  end
236
238
 
237
239
  # common db object options
@@ -3,8 +3,10 @@ require "rails/railtie"
3
3
  module Litestack
4
4
  class Railtie < ::Rails::Railtie
5
5
  initializer :disable_production_sqlite_warning do |app|
6
- # The whole point of this gem is to use sqlite3 in production.
7
- app.config.active_record.sqlite3_production_warning = false
6
+ if config.active_record.key?(:sqlite3_production_warning)
7
+ # The whole point of this gem is to use sqlite3 in production.
8
+ app.config.active_record.sqlite3_production_warning = false
9
+ end
8
10
  end
9
11
  end
10
12
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Litestack
4
- VERSION = "0.4.2"
4
+ VERSION = "0.4.4"
5
5
  end
data/lib/litestack.rb CHANGED
@@ -1,23 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # load core classes
4
- require_relative "./litestack/version"
5
- require_relative "./litestack/litescheduler"
6
- require_relative "./litestack/litesupport"
7
- require_relative "./litestack/litemetric"
8
- require_relative "./litestack/litedb"
9
- require_relative "./litestack/litecache"
10
- require_relative "./litestack/litejob"
11
- require_relative "./litestack/litecable"
4
+ require_relative "litestack/version"
5
+ require_relative "litestack/litescheduler"
6
+ require_relative "litestack/litesupport"
7
+ require_relative "litestack/litemetric"
8
+ require_relative "litestack/litedb"
9
+ require_relative "litestack/litecache"
10
+ require_relative "litestack/litejob"
11
+ require_relative "litestack/litecable"
12
12
 
13
13
  # conditionally load integration with other libraries
14
- require_relative "./sequel/adapters/litedb" if defined? Sequel
15
- require_relative "./active_record/connection_adapters/litedb_adapter" if defined? ActiveRecord
16
- require_relative "./railties/rails/commands/dbconsole" if defined?(Rails) && defined?(ActiveRecord)
17
- require_relative "./active_support/cache/litecache" if defined? ActiveSupport
18
- require_relative "./active_job/queue_adapters/litejob_adapter" if defined? ActiveJob
19
- require_relative "./action_cable/subscription_adapter/litecable" if defined? ActionCable
20
- require_relative "./litestack/railtie" if defined? Rails::Railtie
14
+ require_relative "sequel/adapters/litedb" if defined? Sequel
15
+ require_relative "active_record/connection_adapters/litedb_adapter" if defined? ActiveRecord
16
+ require_relative "railties/rails/commands/dbconsole" if defined?(Rails) && defined?(ActiveRecord)
17
+ require_relative "active_support/cache/litecache" if defined? ActiveSupport
18
+ require_relative "active_job/queue_adapters/litejob_adapter" if defined? ActiveJob
19
+ require_relative "action_cable/subscription_adapter/litecable" if defined? ActionCable
20
+ require_relative "litestack/railtie" if defined? Rails::Railtie
21
21
 
22
22
  module Litestack
23
23
  class NotImplementedError < RuntimeError; end
@@ -27,7 +27,7 @@ module Rails
27
27
 
28
28
  args << db_config.database
29
29
 
30
- find_cmd_and_exec(["mysql", "mysql5"], *args)
30
+ ActiveRecord::Base.connection.class.find_cmd_and_exec(["mysql", "mysql5"], *args)
31
31
 
32
32
  when /^postgres|^postgis/
33
33
  ENV["PGUSER"] = config[:username] if config[:username]
@@ -38,7 +38,7 @@ module Rails
38
38
  ENV["PGSSLCERT"] = config[:sslcert].to_s if config[:sslcert]
39
39
  ENV["PGSSLKEY"] = config[:sslkey].to_s if config[:sslkey]
40
40
  ENV["PGSSLROOTCERT"] = config[:sslrootcert].to_s if config[:sslrootcert]
41
- find_cmd_and_exec("psql", db_config.database)
41
+ ActiveRecord::Base.connection.class.find_cmd_and_exec("psql", db_config.database)
42
42
 
43
43
  when "sqlite3", "litedb"
44
44
  args = []
@@ -47,7 +47,7 @@ module Rails
47
47
  args << "-header" if @options[:header]
48
48
  args << File.expand_path(db_config.database, Rails.respond_to?(:root) ? Rails.root : nil)
49
49
 
50
- find_cmd_and_exec("sqlite3", *args)
50
+ ActiveRecord::Base.connection.class.find_cmd_and_exec("sqlite3", *args)
51
51
 
52
52
  when "oracle", "oracle_enhanced"
53
53
  logon = ""
@@ -58,7 +58,7 @@ module Rails
58
58
  logon << "@#{db_config.database}" if db_config.database
59
59
  end
60
60
 
61
- find_cmd_and_exec("sqlplus", logon)
61
+ ActiveRecord::Base.connection.class.find_cmd_and_exec("sqlplus", logon)
62
62
 
63
63
  when "sqlserver"
64
64
  args = []
@@ -73,7 +73,7 @@ module Rails
73
73
  args += ["-S", host_arg]
74
74
  end
75
75
 
76
- find_cmd_and_exec("sqlcmd", *args)
76
+ ActiveRecord::Base.connection.class.find_cmd_and_exec("sqlcmd", *args)
77
77
 
78
78
  else
79
79
  abort "Unknown command-line client for #{db_config.database}."
@@ -19,6 +19,7 @@ module Sequel
19
19
  sqlite3_opts = {}
20
20
  sqlite3_opts[:readonly] = typecast_value_boolean(opts[:readonly]) if opts.has_key?(:readonly)
21
21
  db = ::Litedb.new(opts[:database].to_s, sqlite3_opts)
22
+ @raw_db = db
22
23
 
23
24
  self.transaction_mode = :immediate
24
25
 
@@ -33,12 +34,19 @@ module Sequel
33
34
  end
34
35
 
35
36
  db.instance_variable_set(:@prepared_statements, {})
36
- @raw_db = db
37
37
  db
38
38
  end
39
+
40
+ def sqlite_version
41
+ @raw_db.sqlite_version
42
+ end
43
+
39
44
  end
40
45
 
41
46
  class Dataset < Sequel::SQLite::Dataset
47
+ def supports_insert_select?
48
+ true
49
+ end
42
50
  end
43
51
  end
44
52
  end
@@ -715,7 +715,7 @@ module Sequel
715
715
 
716
716
  # Handle uniqueness violations when inserting, by using a specified
717
717
  # resolution algorithm. With no options, uses INSERT OR REPLACE. SQLite
718
- # supports the following conflict resolution algoriths: ROLLBACK, ABORT,
718
+ # supports the following conflict resolution algorithms: ROLLBACK, ABORT,
719
719
  # FAIL, IGNORE and REPLACE.
720
720
  #
721
721
  # On SQLite 3.24.0+, you can pass a hash to use an ON CONFLICT clause.
@@ -877,7 +877,7 @@ module Sequel
877
877
  end
878
878
 
879
879
  # Use from_self for aggregate dataset using VALUES.
880
- def aggreate_dataset_use_from_self?
880
+ def aggregate_dataset_use_from_self?
881
881
  super || @opts[:values]
882
882
  end
883
883
 
@@ -17,14 +17,14 @@ Litejobqueue.new({
17
17
  log: nil
18
18
  })
19
19
 
20
- $time = Time.now.to_i #- 10800
20
+ $time = Time.now.to_i # - 10800
21
21
  $start_time = Time.now.to_i
22
22
 
23
23
  class NormalJob
24
24
  include Litejob
25
25
  self.queue = "normal"
26
26
  def perform(time)
27
- $time = time #-= (rand * 100).to_i #10 seconds in the past
27
+ $time = time # -= (rand * 100).to_i #10 seconds in the past
28
28
  sleep 0.001
29
29
  warn "performing some normal action"
30
30
  end
@@ -11,7 +11,7 @@ class Client
11
11
  end
12
12
 
13
13
  def call(*args)
14
- warn "[#{Process.pid}]:#{object_id} recieved #{args} from #{@channel}"
14
+ warn "[#{Process.pid}]:#{object_id} received #{args} from #{@channel}"
15
15
  end
16
16
  end
17
17