litestack 0.4.2 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.standard.yml +3 -1
- data/BENCHMARKS.md +3 -3
- data/CAVEATS.md +20 -0
- data/CHANGELOG.md +40 -1
- data/FILESYSTEMS.md +55 -0
- data/Gemfile +2 -0
- data/README.md +8 -4
- data/ROADMAP.md +6 -6
- data/assets/litestack_advantage.png +0 -0
- data/bench/bench.rb +2 -0
- data/bench/bench_cache_rails.rb +33 -2
- data/bench/bench_cache_raw.rb +36 -12
- data/bench/bench_jobs_rails.rb +3 -3
- data/bench/bench_jobs_raw.rb +3 -3
- data/bin/liteboard +16 -13
- data/gemfiles/rails70.gemfile +5 -0
- data/gemfiles/rails71.gemfile +5 -0
- data/gemfiles/rails71.gemfile.lock +264 -0
- data/lib/active_job/queue_adapters/litejob_adapter.rb +11 -3
- data/lib/active_record/connection_adapters/litedb_adapter.rb +8 -0
- data/lib/active_support/cache/litecache.rb +40 -7
- data/lib/generators/litestack/install/install_generator.rb +2 -2
- data/lib/generators/litestack/install/templates/cable.yml +0 -3
- data/lib/litestack/liteboard/liteboard.rb +15 -19
- data/lib/litestack/liteboard/views/litecable.erb +1 -1
- data/lib/litestack/litecable.rb +1 -1
- data/lib/litestack/litecache.rb +51 -19
- data/lib/litestack/litecache.sql.yml +7 -5
- data/lib/litestack/litedb.rb +5 -1
- data/lib/litestack/litejob.rb +1 -1
- data/lib/litestack/litejobqueue.rb +24 -14
- data/lib/litestack/litemetric.rb +7 -6
- data/lib/litestack/litemetric.sql.yml +1 -1
- data/lib/litestack/litemetric_collector.sql.yml +1 -1
- data/lib/litestack/litequeue.rb +17 -2
- data/lib/litestack/litequeue.sql.yml +38 -5
- data/lib/litestack/litescheduler.rb +9 -4
- data/lib/litestack/litesearch/index.rb +11 -10
- data/lib/litestack/litesearch/model.rb +61 -3
- data/lib/litestack/litesearch/schema.rb +7 -2
- data/lib/litestack/litesearch/schema_adapters/backed_adapter.rb +69 -25
- data/lib/litestack/litesearch/schema_adapters.rb +4 -4
- data/lib/litestack/litesearch.rb +2 -2
- data/lib/litestack/litesupport.rb +9 -7
- data/lib/litestack/railtie.rb +4 -2
- data/lib/litestack/version.rb +1 -1
- data/lib/litestack.rb +15 -15
- data/lib/railties/rails/commands/dbconsole.rb +5 -5
- data/lib/sequel/adapters/litedb.rb +9 -1
- data/lib/sequel/adapters/shared/litedb.rb +2 -2
- data/scripts/build_metrics.rb +2 -2
- data/scripts/test_cable.rb +1 -1
- metadata +105 -56
- 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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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"
|
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 << "
|
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
|
129
|
-
|
164
|
+
|
165
|
+
def joins_sql
|
166
|
+
joins = [@schema[:table]]
|
130
167
|
active_fields.each do |name, field|
|
131
|
-
|
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
|
-
|
183
|
+
joins.join(" LEFT JOIN ")
|
134
184
|
end
|
135
185
|
|
136
|
-
|
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 "
|
2
|
-
require_relative "
|
3
|
-
require_relative "
|
4
|
-
require_relative "
|
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"
|
data/lib/litestack/litesearch.rb
CHANGED
@@ -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 "
|
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
|
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.
|
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
|
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
|
-
|
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
|
data/lib/litestack/railtie.rb
CHANGED
@@ -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
|
-
|
7
|
-
|
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
|
data/lib/litestack/version.rb
CHANGED
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 "
|
5
|
-
require_relative "
|
6
|
-
require_relative "
|
7
|
-
require_relative "
|
8
|
-
require_relative "
|
9
|
-
require_relative "
|
10
|
-
require_relative "
|
11
|
-
require_relative "
|
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 "
|
15
|
-
require_relative "
|
16
|
-
require_relative "
|
17
|
-
require_relative "
|
18
|
-
require_relative "
|
19
|
-
require_relative "
|
20
|
-
require_relative "
|
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
|
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
|
880
|
+
def aggregate_dataset_use_from_self?
|
881
881
|
super || @opts[:values]
|
882
882
|
end
|
883
883
|
|
data/scripts/build_metrics.rb
CHANGED
@@ -17,14 +17,14 @@ Litejobqueue.new({
|
|
17
17
|
log: nil
|
18
18
|
})
|
19
19
|
|
20
|
-
$time = Time.now.to_i
|
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
|
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
|