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
@@ -0,0 +1,264 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
litestack (0.4.4)
|
5
|
+
erubi
|
6
|
+
oj
|
7
|
+
rack
|
8
|
+
rackup
|
9
|
+
sqlite3
|
10
|
+
tilt
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: https://rubygems.org/
|
14
|
+
specs:
|
15
|
+
actioncable (7.1.3.2)
|
16
|
+
actionpack (= 7.1.3.2)
|
17
|
+
activesupport (= 7.1.3.2)
|
18
|
+
nio4r (~> 2.0)
|
19
|
+
websocket-driver (>= 0.6.1)
|
20
|
+
zeitwerk (~> 2.6)
|
21
|
+
actionmailbox (7.1.3.2)
|
22
|
+
actionpack (= 7.1.3.2)
|
23
|
+
activejob (= 7.1.3.2)
|
24
|
+
activerecord (= 7.1.3.2)
|
25
|
+
activestorage (= 7.1.3.2)
|
26
|
+
activesupport (= 7.1.3.2)
|
27
|
+
mail (>= 2.7.1)
|
28
|
+
net-imap
|
29
|
+
net-pop
|
30
|
+
net-smtp
|
31
|
+
actionmailer (7.1.3.2)
|
32
|
+
actionpack (= 7.1.3.2)
|
33
|
+
actionview (= 7.1.3.2)
|
34
|
+
activejob (= 7.1.3.2)
|
35
|
+
activesupport (= 7.1.3.2)
|
36
|
+
mail (~> 2.5, >= 2.5.4)
|
37
|
+
net-imap
|
38
|
+
net-pop
|
39
|
+
net-smtp
|
40
|
+
rails-dom-testing (~> 2.2)
|
41
|
+
actionpack (7.1.3.2)
|
42
|
+
actionview (= 7.1.3.2)
|
43
|
+
activesupport (= 7.1.3.2)
|
44
|
+
nokogiri (>= 1.8.5)
|
45
|
+
racc
|
46
|
+
rack (>= 2.2.4)
|
47
|
+
rack-session (>= 1.0.1)
|
48
|
+
rack-test (>= 0.6.3)
|
49
|
+
rails-dom-testing (~> 2.2)
|
50
|
+
rails-html-sanitizer (~> 1.6)
|
51
|
+
actiontext (7.1.3.2)
|
52
|
+
actionpack (= 7.1.3.2)
|
53
|
+
activerecord (= 7.1.3.2)
|
54
|
+
activestorage (= 7.1.3.2)
|
55
|
+
activesupport (= 7.1.3.2)
|
56
|
+
globalid (>= 0.6.0)
|
57
|
+
nokogiri (>= 1.8.5)
|
58
|
+
actionview (7.1.3.2)
|
59
|
+
activesupport (= 7.1.3.2)
|
60
|
+
builder (~> 3.1)
|
61
|
+
erubi (~> 1.11)
|
62
|
+
rails-dom-testing (~> 2.2)
|
63
|
+
rails-html-sanitizer (~> 1.6)
|
64
|
+
activejob (7.1.3.2)
|
65
|
+
activesupport (= 7.1.3.2)
|
66
|
+
globalid (>= 0.3.6)
|
67
|
+
activemodel (7.1.3.2)
|
68
|
+
activesupport (= 7.1.3.2)
|
69
|
+
activerecord (7.1.3.2)
|
70
|
+
activemodel (= 7.1.3.2)
|
71
|
+
activesupport (= 7.1.3.2)
|
72
|
+
timeout (>= 0.4.0)
|
73
|
+
activestorage (7.1.3.2)
|
74
|
+
actionpack (= 7.1.3.2)
|
75
|
+
activejob (= 7.1.3.2)
|
76
|
+
activerecord (= 7.1.3.2)
|
77
|
+
activesupport (= 7.1.3.2)
|
78
|
+
marcel (~> 1.0)
|
79
|
+
activesupport (7.1.3.2)
|
80
|
+
base64
|
81
|
+
bigdecimal
|
82
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
83
|
+
connection_pool (>= 2.2.5)
|
84
|
+
drb
|
85
|
+
i18n (>= 1.6, < 2)
|
86
|
+
minitest (>= 5.1)
|
87
|
+
mutex_m
|
88
|
+
tzinfo (~> 2.0)
|
89
|
+
ast (2.4.2)
|
90
|
+
base64 (0.2.0)
|
91
|
+
bigdecimal (3.1.6)
|
92
|
+
builder (3.2.4)
|
93
|
+
concurrent-ruby (1.2.3)
|
94
|
+
connection_pool (2.4.1)
|
95
|
+
crass (1.0.6)
|
96
|
+
date (3.3.4)
|
97
|
+
docile (1.4.0)
|
98
|
+
drb (2.2.1)
|
99
|
+
erubi (1.12.0)
|
100
|
+
globalid (1.2.1)
|
101
|
+
activesupport (>= 6.1)
|
102
|
+
hanami-router (0.6.2)
|
103
|
+
hanami-utils (~> 0.7)
|
104
|
+
http_router (~> 0.11)
|
105
|
+
hanami-utils (0.9.2)
|
106
|
+
http_router (0.11.2)
|
107
|
+
rack (>= 1.0.0)
|
108
|
+
url_mount (~> 0.2.1)
|
109
|
+
i18n (1.14.1)
|
110
|
+
concurrent-ruby (~> 1.0)
|
111
|
+
io-console (0.7.2)
|
112
|
+
irb (1.11.2)
|
113
|
+
rdoc
|
114
|
+
reline (>= 0.4.2)
|
115
|
+
json (2.7.1)
|
116
|
+
language_server-protocol (3.17.0.3)
|
117
|
+
lint_roller (1.1.0)
|
118
|
+
loofah (2.22.0)
|
119
|
+
crass (~> 1.0.2)
|
120
|
+
nokogiri (>= 1.12.0)
|
121
|
+
mail (2.8.1)
|
122
|
+
mini_mime (>= 0.1.1)
|
123
|
+
net-imap
|
124
|
+
net-pop
|
125
|
+
net-smtp
|
126
|
+
marcel (1.0.4)
|
127
|
+
mini_mime (1.1.5)
|
128
|
+
minitest (5.22.2)
|
129
|
+
mutex_m (0.2.0)
|
130
|
+
net-imap (0.4.10)
|
131
|
+
date
|
132
|
+
net-protocol
|
133
|
+
net-pop (0.1.2)
|
134
|
+
net-protocol
|
135
|
+
net-protocol (0.2.2)
|
136
|
+
timeout
|
137
|
+
net-smtp (0.4.0.1)
|
138
|
+
net-protocol
|
139
|
+
nio4r (2.7.0)
|
140
|
+
nokogiri (1.16.2-arm64-darwin)
|
141
|
+
racc (~> 1.4)
|
142
|
+
oj (3.16.3)
|
143
|
+
bigdecimal (>= 3.0)
|
144
|
+
parallel (1.24.0)
|
145
|
+
parser (3.3.0.5)
|
146
|
+
ast (~> 2.4.1)
|
147
|
+
racc
|
148
|
+
psych (5.1.2)
|
149
|
+
stringio
|
150
|
+
racc (1.7.3)
|
151
|
+
rack (3.0.9.1)
|
152
|
+
rack-session (2.0.0)
|
153
|
+
rack (>= 3.0.0)
|
154
|
+
rack-test (2.1.0)
|
155
|
+
rack (>= 1.3)
|
156
|
+
rackup (2.1.0)
|
157
|
+
rack (>= 3)
|
158
|
+
webrick (~> 1.8)
|
159
|
+
rails (7.1.3.2)
|
160
|
+
actioncable (= 7.1.3.2)
|
161
|
+
actionmailbox (= 7.1.3.2)
|
162
|
+
actionmailer (= 7.1.3.2)
|
163
|
+
actionpack (= 7.1.3.2)
|
164
|
+
actiontext (= 7.1.3.2)
|
165
|
+
actionview (= 7.1.3.2)
|
166
|
+
activejob (= 7.1.3.2)
|
167
|
+
activemodel (= 7.1.3.2)
|
168
|
+
activerecord (= 7.1.3.2)
|
169
|
+
activestorage (= 7.1.3.2)
|
170
|
+
activesupport (= 7.1.3.2)
|
171
|
+
bundler (>= 1.15.0)
|
172
|
+
railties (= 7.1.3.2)
|
173
|
+
rails-dom-testing (2.2.0)
|
174
|
+
activesupport (>= 5.0.0)
|
175
|
+
minitest
|
176
|
+
nokogiri (>= 1.6)
|
177
|
+
rails-html-sanitizer (1.6.0)
|
178
|
+
loofah (~> 2.21)
|
179
|
+
nokogiri (~> 1.14)
|
180
|
+
railties (7.1.3.2)
|
181
|
+
actionpack (= 7.1.3.2)
|
182
|
+
activesupport (= 7.1.3.2)
|
183
|
+
irb
|
184
|
+
rackup (>= 1.0.0)
|
185
|
+
rake (>= 12.2)
|
186
|
+
thor (~> 1.0, >= 1.2.2)
|
187
|
+
zeitwerk (~> 2.6)
|
188
|
+
rainbow (3.1.1)
|
189
|
+
rake (13.1.0)
|
190
|
+
rdoc (6.6.2)
|
191
|
+
psych (>= 4.0.0)
|
192
|
+
regexp_parser (2.9.0)
|
193
|
+
reline (0.4.3)
|
194
|
+
io-console (~> 0.5)
|
195
|
+
rexml (3.2.6)
|
196
|
+
rubocop (1.61.0)
|
197
|
+
json (~> 2.3)
|
198
|
+
language_server-protocol (>= 3.17.0)
|
199
|
+
parallel (~> 1.10)
|
200
|
+
parser (>= 3.3.0.2)
|
201
|
+
rainbow (>= 2.2.2, < 4.0)
|
202
|
+
regexp_parser (>= 1.8, < 3.0)
|
203
|
+
rexml (>= 3.2.5, < 4.0)
|
204
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
205
|
+
ruby-progressbar (~> 1.7)
|
206
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
207
|
+
rubocop-ast (1.31.1)
|
208
|
+
parser (>= 3.3.0.4)
|
209
|
+
rubocop-performance (1.20.2)
|
210
|
+
rubocop (>= 1.48.1, < 2.0)
|
211
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
212
|
+
ruby-progressbar (1.13.0)
|
213
|
+
sequel (5.78.0)
|
214
|
+
bigdecimal
|
215
|
+
simplecov (0.22.0)
|
216
|
+
docile (~> 1.1)
|
217
|
+
simplecov-html (~> 0.11)
|
218
|
+
simplecov_json_formatter (~> 0.1)
|
219
|
+
simplecov-html (0.12.3)
|
220
|
+
simplecov_json_formatter (0.1.4)
|
221
|
+
sqlite3 (1.7.2-arm64-darwin)
|
222
|
+
standard (1.34.0)
|
223
|
+
language_server-protocol (~> 3.17.0.2)
|
224
|
+
lint_roller (~> 1.0)
|
225
|
+
rubocop (~> 1.60)
|
226
|
+
standard-custom (~> 1.0.0)
|
227
|
+
standard-performance (~> 1.3)
|
228
|
+
standard-custom (1.0.2)
|
229
|
+
lint_roller (~> 1.0)
|
230
|
+
rubocop (~> 1.50)
|
231
|
+
standard-performance (1.3.1)
|
232
|
+
lint_roller (~> 1.1)
|
233
|
+
rubocop-performance (~> 1.20.2)
|
234
|
+
stringio (3.1.0)
|
235
|
+
thor (1.3.1)
|
236
|
+
tilt (2.3.0)
|
237
|
+
timeout (0.4.1)
|
238
|
+
tzinfo (2.0.6)
|
239
|
+
concurrent-ruby (~> 1.0)
|
240
|
+
unicode-display_width (2.5.0)
|
241
|
+
url_mount (0.2.1)
|
242
|
+
rack
|
243
|
+
webrick (1.8.1)
|
244
|
+
websocket-driver (0.7.6)
|
245
|
+
websocket-extensions (>= 0.1.0)
|
246
|
+
websocket-extensions (0.1.5)
|
247
|
+
zeitwerk (2.6.13)
|
248
|
+
|
249
|
+
PLATFORMS
|
250
|
+
arm64-darwin
|
251
|
+
|
252
|
+
DEPENDENCIES
|
253
|
+
litestack!
|
254
|
+
minitest
|
255
|
+
rack (~> 3.0)
|
256
|
+
rails (~> 7.1)
|
257
|
+
railties
|
258
|
+
rake
|
259
|
+
sequel
|
260
|
+
simplecov
|
261
|
+
standard
|
262
|
+
|
263
|
+
BUNDLED WITH
|
264
|
+
2.5.3
|
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../../litestack/litejob"
|
4
|
+
require "active_support"
|
4
5
|
require "active_support/core_ext/enumerable"
|
6
|
+
require "active_support/core_ext/numeric/time"
|
5
7
|
require "active_support/core_ext/array/access"
|
6
8
|
require "active_job"
|
7
9
|
|
@@ -18,20 +20,26 @@ module ActiveJob
|
|
18
20
|
# Job.options = DEFAULT_OPTIONS.merge(options)
|
19
21
|
end
|
20
22
|
|
23
|
+
def enqueue_after_transaction_commit?
|
24
|
+
Job.options[:enqueue_after_transaction_commit]
|
25
|
+
end
|
26
|
+
|
21
27
|
def enqueue(job) # :nodoc:
|
22
28
|
Job.queue = job.queue_name
|
23
29
|
Job.perform_async(job.serialize)
|
24
30
|
end
|
25
31
|
|
26
|
-
def enqueue_at(job,
|
32
|
+
def enqueue_at(job, time) # :nodoc:
|
33
|
+
time = time.from_now if time.respond_to?(:from_now) #is_a?(ActiveSupport::Duration)
|
27
34
|
Job.queue = job.queue_name
|
28
|
-
Job.perform_at(
|
35
|
+
Job.perform_at(time, job.serialize)
|
29
36
|
end
|
30
37
|
|
31
38
|
class Job # :nodoc:
|
32
39
|
DEFAULT_OPTIONS = {
|
33
40
|
config_path: "./config/litejob.yml",
|
34
|
-
logger: nil # Rails performs its logging already
|
41
|
+
logger: nil, # Rails performs its logging already
|
42
|
+
enqueue_after_transaction_commit: true
|
35
43
|
}
|
36
44
|
|
37
45
|
include ::Litejob
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative "../../litestack/litedb"
|
2
|
+
|
2
3
|
require "active_record"
|
3
4
|
require "active_record/connection_adapters/sqlite3_adapter"
|
4
5
|
require "active_record/tasks/sqlite_database_tasks"
|
@@ -90,3 +91,10 @@ module ActiveRecord
|
|
90
91
|
end
|
91
92
|
end
|
92
93
|
end
|
94
|
+
|
95
|
+
ActiveRecord::ConnectionAdapters.register(
|
96
|
+
"litedb", "ActiveRecord::ConnectionAdapters::LitedbAdapter",
|
97
|
+
"active_record/connection_adapters/litedb_adapter"
|
98
|
+
) if ActiveRecord::ConnectionAdapters.respond_to?(:register)
|
99
|
+
|
100
|
+
|
@@ -1,14 +1,16 @@
|
|
1
|
-
require "
|
2
|
-
require "active_support/core_ext/enumerable"
|
3
|
-
require "active_support/core_ext/array/extract_options"
|
1
|
+
require "active_support"
|
4
2
|
require "active_support/core_ext/numeric/time"
|
5
3
|
require "active_support/cache"
|
4
|
+
|
6
5
|
require_relative "../../litestack/litecache"
|
7
6
|
|
8
7
|
module ActiveSupport
|
9
8
|
module Cache
|
9
|
+
|
10
|
+
self.format_version = 7.0
|
11
|
+
|
10
12
|
class Litecache < Store
|
11
|
-
prepend Strategy::LocalCache
|
13
|
+
# prepend Strategy::LocalCache
|
12
14
|
|
13
15
|
def self.supports_cache_versioning?
|
14
16
|
true
|
@@ -25,17 +27,22 @@ module ActiveSupport
|
|
25
27
|
options = merged_options(options)
|
26
28
|
# todo: fix me
|
27
29
|
# this is currently a hack to avoid dealing with Rails cache encoding and decoding
|
30
|
+
# and it can result in a race condition as it stands
|
28
31
|
# @cache.transaction(:immediate) do
|
32
|
+
# currently transactions are not compatible with acquiring connections
|
33
|
+
# this needs fixing by storing the connection to the context once acquired
|
29
34
|
if (value = read(key, options))
|
30
35
|
value = value.to_i + amount
|
31
36
|
write(key, value, options)
|
37
|
+
else
|
38
|
+
write(key, amount, options)
|
32
39
|
end
|
33
40
|
# end
|
34
41
|
end
|
35
42
|
|
36
43
|
def decrement(key, amount = 1, options = nil)
|
37
44
|
options = merged_options(options)
|
38
|
-
increment(key, -1 * amount, options
|
45
|
+
increment(key, -1 * amount, options)
|
39
46
|
end
|
40
47
|
|
41
48
|
def prune(limit = nil, time = nil)
|
@@ -46,7 +53,7 @@ module ActiveSupport
|
|
46
53
|
@cache.prune(limit)
|
47
54
|
end
|
48
55
|
|
49
|
-
def clear
|
56
|
+
def clear(options = nil)
|
50
57
|
@cache.clear
|
51
58
|
end
|
52
59
|
|
@@ -68,18 +75,44 @@ module ActiveSupport
|
|
68
75
|
|
69
76
|
private
|
70
77
|
|
78
|
+
def serialize_entries(entry, **options)
|
79
|
+
Marshal.dump(entry)
|
80
|
+
end
|
81
|
+
|
82
|
+
def deserialize_entries(entry)
|
83
|
+
Marshal.load(entry.to_s)
|
84
|
+
end
|
85
|
+
|
71
86
|
# Read an entry from the cache.
|
72
87
|
def read_entry(key, **options)
|
73
88
|
deserialize_entry(@cache.get(key))
|
74
89
|
end
|
75
90
|
|
91
|
+
def read_multi_entries(names, **options)
|
92
|
+
results = {}
|
93
|
+
return results if names == []
|
94
|
+
rs = @cache.get_multi(*names.flatten)
|
95
|
+
rs.each_pair { |k, v| results[k] = deserialize_entry(v).value }
|
96
|
+
results
|
97
|
+
end
|
98
|
+
|
76
99
|
# Write an entry to the cache.
|
77
100
|
def write_entry(key, entry, **options)
|
78
101
|
write_serialized_entry(key, serialize_entry(entry, **options), **options)
|
79
102
|
end
|
80
103
|
|
104
|
+
def write_multi_entries(entries, **options)
|
105
|
+
return if entries.empty?
|
106
|
+
entries.each_pair { |k, v| entries[k] = serialize_entry(v, **options) }
|
107
|
+
expires_in = options[:expires_in].to_i if options[:expires_in]
|
108
|
+
if options[:race_condition_ttl] && expires_in > 0 && !options[:raw]
|
109
|
+
expires_in += 5.minutes
|
110
|
+
end
|
111
|
+
@cache.set_multi(entries, expires_in)
|
112
|
+
end
|
113
|
+
|
81
114
|
def write_serialized_entry(key, payload, **options)
|
82
|
-
expires_in = options[:expires_in].to_i
|
115
|
+
expires_in = options[:expires_in].to_i if options[:expires_in]
|
83
116
|
if options[:race_condition_ttl] && expires_in > 0 && !options[:raw]
|
84
117
|
expires_in += 5.minutes
|
85
118
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
class Litestack::InstallGenerator < Rails::Generators::Base
|
2
2
|
source_root File.expand_path("templates", __dir__)
|
3
3
|
|
4
|
-
# Force copy
|
4
|
+
# Force copy configuration files so Rails installs don't ask questions
|
5
5
|
# that less experienced people might not understand. The more Sr folks.
|
6
6
|
# will know to check git to look at what changed.
|
7
|
-
def
|
7
|
+
def modify_database_adapter
|
8
8
|
copy_file "database.yml", "config/database.yml", force: true
|
9
9
|
end
|
10
10
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "rack"
|
4
4
|
require "tilt"
|
5
5
|
require "erubi"
|
6
6
|
|
@@ -11,37 +11,32 @@ class Liteboard
|
|
11
11
|
@@resolutions = {"minute" => [300, 12], "hour" => [3600, 24], "day" => [3600 * 24, 7], "week" => [3600 * 24 * 7, 53], "year" => [3600 * 24 * 365, 100]}
|
12
12
|
@@res_mapping = {"hour" => "minute", "day" => "hour", "week" => "day", "year" => "week"}
|
13
13
|
@@templates = {}
|
14
|
-
@@app =
|
15
|
-
|
14
|
+
@@app = proc do |env|
|
15
|
+
case path = env["PATH_INFO"]
|
16
|
+
when "/"
|
16
17
|
Liteboard.new(env).call(:index)
|
17
|
-
|
18
|
-
|
19
|
-
get "/topics/Litejob", to: ->(env) do
|
18
|
+
when "/topics/Litejob"
|
20
19
|
Liteboard.new(env).call(:litejob)
|
21
|
-
|
22
|
-
|
23
|
-
get "/topics/Litecache", to: ->(env) do
|
20
|
+
when "/topics/Litecache"
|
24
21
|
Liteboard.new(env).call(:litecache)
|
25
|
-
|
26
|
-
|
27
|
-
get "/topics/Litedb", to: ->(env) do
|
22
|
+
when "/topics/Litedb"
|
28
23
|
Liteboard.new(env).call(:litedb)
|
29
|
-
|
30
|
-
|
31
|
-
get "/topics/Litecable", to: ->(env) do
|
24
|
+
when "/topics/Litecable"
|
32
25
|
Liteboard.new(env).call(:litecable)
|
33
26
|
end
|
27
|
+
|
34
28
|
end
|
35
29
|
|
36
30
|
def initialize(env)
|
37
31
|
@env = env
|
38
|
-
@
|
32
|
+
@req = Rack::Request.new(@env)
|
33
|
+
@params = @req.params
|
39
34
|
@running = true
|
40
35
|
@lm = Litemetric.instance
|
41
36
|
end
|
42
37
|
|
43
38
|
def params(key)
|
44
|
-
URI.decode_uri_component(@params[key].to_s)
|
39
|
+
URI.decode_uri_component(@params[key.to_s].to_s)
|
45
40
|
end
|
46
41
|
|
47
42
|
def call(method)
|
@@ -227,9 +222,9 @@ class Liteboard
|
|
227
222
|
@topic = "Litejob"
|
228
223
|
@events = @lm.events_summaries(@topic, @resolution, @order, @dir, @search, @step * @count)
|
229
224
|
@events.each do |event|
|
230
|
-
data_points = @lm.event_data_points(@step, @count, @resolution, @topic, event[
|
225
|
+
data_points = @lm.event_data_points(@step, @count, @resolution, @topic, event[:name])
|
231
226
|
event["counts"] = data_points.collect { |r| [r["rtime"], r["rcount"] || 0] }
|
232
|
-
event["values"] = data_points.collect { |r| [r["rtime"], r["rtotal"] || 0] }
|
227
|
+
event["values"] = data_points.collect { |r| [r["rtime"], (r["rtotal"] || 0.0)] }
|
233
228
|
end
|
234
229
|
@snapshot = read_snapshot(@topic)
|
235
230
|
@size = begin
|
@@ -391,6 +386,7 @@ class Liteboard
|
|
391
386
|
end
|
392
387
|
|
393
388
|
def format(float)
|
389
|
+
float = float.round(3)
|
394
390
|
string = float.to_s
|
395
391
|
whole, decimal = string.split(".")
|
396
392
|
whole = whole.chars.reverse.each_slice(3).map(&:join).join(",").reverse
|
@@ -61,7 +61,7 @@
|
|
61
61
|
</div>
|
62
62
|
<div class="card-body">
|
63
63
|
<span class="hidden inlinestackedcolumn">
|
64
|
-
<%=[["Time", "
|
64
|
+
<%=[["Time", "Received Count", "Delivered Count"]] + @messages_over_time.to_a%>
|
65
65
|
</span>
|
66
66
|
</div>
|
67
67
|
</div>
|
data/lib/litestack/litecable.rb
CHANGED
@@ -113,7 +113,7 @@ class Litecable
|
|
113
113
|
def create_listener
|
114
114
|
Litescheduler.spawn do
|
115
115
|
while @running
|
116
|
-
@last_fetched_id ||=
|
116
|
+
@last_fetched_id ||= run_stmt(:last_id)[0][0] || 0
|
117
117
|
run_stmt(:fetch, @last_fetched_id, @pid).to_a.each do |msg|
|
118
118
|
@logger.info "RECEIVED #{msg}"
|
119
119
|
@last_fetched_id = msg[0]
|
data/lib/litestack/litecache.rb
CHANGED
@@ -20,13 +20,13 @@ class Litecache
|
|
20
20
|
include Litemetric::Measurable
|
21
21
|
|
22
22
|
# the default options for the cache
|
23
|
-
# can be
|
23
|
+
# can be overridden by passing new options in a hash
|
24
24
|
# to Litecache.new
|
25
25
|
# path: "./cache.db"
|
26
26
|
# expiry: 60 * 60 * 24 * 30 -> one month default expiry if none is provided
|
27
27
|
# size: 128 * 1024 * 1024 -> 128MB
|
28
28
|
# mmap_size: 128 * 1024 * 1024 -> 128MB to be held in memory
|
29
|
-
# min_size: 32 * 1024 ->
|
29
|
+
# min_size: 32 * 1024 -> 32KB
|
30
30
|
# return_full_record: false -> only return the payload
|
31
31
|
# sleep_interval: 1 -> 1 second of sleep between cleanup runs
|
32
32
|
|
@@ -39,7 +39,7 @@ class Litecache
|
|
39
39
|
mmap_size: 128 * 1024 * 1024, # 128MB
|
40
40
|
min_size: 8 * 1024 * 1024, # 16MB
|
41
41
|
return_full_record: false, # only return the payload
|
42
|
-
sleep_interval:
|
42
|
+
sleep_interval: 30, # 30 seconds
|
43
43
|
metrics: false
|
44
44
|
}
|
45
45
|
|
@@ -63,15 +63,15 @@ class Litecache
|
|
63
63
|
|
64
64
|
def initialize(options = {})
|
65
65
|
options[:size] = DEFAULT_OPTIONS[:min_size] if options[:size] && options[:size] < DEFAULT_OPTIONS[:min_size]
|
66
|
-
@last_visited = {}
|
67
66
|
init(options)
|
67
|
+
@expires_in = @options[:expiry] || 60 * 60 * 24 * 30
|
68
68
|
collect_metrics if @options[:metrics]
|
69
69
|
end
|
70
70
|
|
71
71
|
# add a key, value pair to the cache, with an optional expiry value (number of seconds)
|
72
72
|
def set(key, value, expires_in = nil)
|
73
73
|
key = key.to_s
|
74
|
-
expires_in
|
74
|
+
expires_in ||= @expires_in
|
75
75
|
@conn.acquire do |cache|
|
76
76
|
cache.stmts[:setter].execute!(key, value, expires_in)
|
77
77
|
capture(:set, key)
|
@@ -83,10 +83,27 @@ class Litecache
|
|
83
83
|
true
|
84
84
|
end
|
85
85
|
|
86
|
+
# set multiple keys and values in one shot set_multi({k1: v1, k2: v2, ... })
|
87
|
+
def set_multi(keys_and_values, expires_in = nil)
|
88
|
+
expires_in ||= @expires_in
|
89
|
+
transaction do |conn|
|
90
|
+
keys_and_values.each_pair do |k, v|
|
91
|
+
key = k.to_s
|
92
|
+
conn.stmts[:setter].execute!(key, v, expires_in)
|
93
|
+
capture(:set, key)
|
94
|
+
rescue SQLite3::FullException
|
95
|
+
conn.stmts[:extra_pruner].execute!(0.2)
|
96
|
+
conn.execute("vacuum")
|
97
|
+
retry
|
98
|
+
end
|
99
|
+
end
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
86
103
|
# add a key, value pair to the cache, but only if the key doesn't exist, with an optional expiry value (number of seconds)
|
87
104
|
def set_unless_exists(key, value, expires_in = nil)
|
88
105
|
key = key.to_s
|
89
|
-
expires_in
|
106
|
+
expires_in ||= @expires_in
|
90
107
|
changes = 0
|
91
108
|
@conn.acquire do |cache|
|
92
109
|
cache.transaction(:immediate) do
|
@@ -107,7 +124,6 @@ class Litecache
|
|
107
124
|
def get(key)
|
108
125
|
key = key.to_s
|
109
126
|
if (record = @conn.acquire { |cache| cache.stmts[:getter].execute!(key)[0] })
|
110
|
-
@last_visited[key] = true
|
111
127
|
capture(:get, key, 1)
|
112
128
|
return record[1]
|
113
129
|
end
|
@@ -115,6 +131,24 @@ class Litecache
|
|
115
131
|
nil
|
116
132
|
end
|
117
133
|
|
134
|
+
# get multiple values by their keys, a hash with values corresponding to the keys
|
135
|
+
# is returned,
|
136
|
+
def get_multi(*keys)
|
137
|
+
results = {}
|
138
|
+
transaction(:deferred) do |conn|
|
139
|
+
keys.length.times do |i|
|
140
|
+
key = keys[i].to_s
|
141
|
+
if (record = conn.stmts[:getter].execute!(key)[0])
|
142
|
+
results[keys[i]] = record[1] # use the original key format
|
143
|
+
capture(:get, key, 1)
|
144
|
+
else
|
145
|
+
capture(:get, key, 0)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
results
|
150
|
+
end
|
151
|
+
|
118
152
|
# delete a key, value pair from the cache
|
119
153
|
def delete(key)
|
120
154
|
changes = 0
|
@@ -126,13 +160,13 @@ class Litecache
|
|
126
160
|
end
|
127
161
|
|
128
162
|
# increment an integer value by amount, optionally add an expiry value (in seconds)
|
129
|
-
def increment(key, amount, expires_in = nil)
|
163
|
+
def increment(key, amount = 1, expires_in = nil)
|
130
164
|
expires_in ||= @expires_in
|
131
165
|
@conn.acquire { |cache| cache.stmts[:incrementer].execute!(key.to_s, amount, expires_in) }
|
132
166
|
end
|
133
167
|
|
134
168
|
# decrement an integer value by amount, optionally add an expiry value (in seconds)
|
135
|
-
def decrement(key, amount, expires_in = nil)
|
169
|
+
def decrement(key, amount = 1, expires_in = nil)
|
136
170
|
increment(key, -amount, expires_in)
|
137
171
|
end
|
138
172
|
|
@@ -189,11 +223,14 @@ class Litecache
|
|
189
223
|
end
|
190
224
|
|
191
225
|
# low level access to SQLite transactions, use with caution
|
192
|
-
def transaction(mode
|
193
|
-
return cache.transaction(mode) { yield } unless acquire
|
226
|
+
def transaction(mode = :immediate)
|
194
227
|
@conn.acquire do |cache|
|
195
|
-
cache.
|
228
|
+
if cache.transaction_active?
|
196
229
|
yield
|
230
|
+
else
|
231
|
+
cache.transaction(mode) do
|
232
|
+
yield cache
|
233
|
+
end
|
197
234
|
end
|
198
235
|
end
|
199
236
|
end
|
@@ -202,19 +239,14 @@ class Litecache
|
|
202
239
|
|
203
240
|
def setup
|
204
241
|
super # create connection
|
205
|
-
@bgthread = spawn_worker # create
|
242
|
+
@bgthread = spawn_worker # create background pruner thread
|
206
243
|
end
|
207
244
|
|
208
245
|
def spawn_worker
|
209
246
|
Litescheduler.spawn do
|
210
247
|
while @running
|
211
248
|
@conn.acquire do |cache|
|
212
|
-
cache.
|
213
|
-
@last_visited.delete_if do |k| # there is a race condition here, but not a serious one
|
214
|
-
cache.stmts[:toucher].execute!(k) || true
|
215
|
-
end
|
216
|
-
cache.stmts[:pruner].execute!
|
217
|
-
end
|
249
|
+
cache.stmts[:pruner].execute!
|
218
250
|
rescue SQLite3::BusyException
|
219
251
|
retry
|
220
252
|
rescue SQLite3::FullException
|