scrolls 0.3.9 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +2 -0
- data/README.md +53 -14
- data/Rakefile +4 -2
- data/docs/global-context.md +1 -1
- data/docs/syslog.md +14 -1
- data/lib/scrolls/{iolog.rb → iologger.rb} +4 -2
- data/lib/scrolls/logger.rb +323 -0
- data/lib/scrolls/parser.rb +4 -2
- data/lib/scrolls/sysloglogger.rb +17 -0
- data/lib/scrolls/utils.rb +55 -13
- data/lib/scrolls/version.rb +1 -1
- data/lib/scrolls.rb +57 -77
- data/test/test_helper.rb +4 -1
- data/test/test_parser.rb +17 -2
- data/test/test_scrolls.rb +58 -47
- metadata +6 -10
- data/lib/scrolls/atomic.rb +0 -59
- data/lib/scrolls/log.rb +0 -262
- data/lib/scrolls/syslog.rb +0 -46
- data/test/test_atomic.rb +0 -33
data/lib/scrolls.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
require "
|
2
|
-
require "scrolls/atomic"
|
3
|
-
require "scrolls/log"
|
1
|
+
require "scrolls/logger"
|
4
2
|
require "scrolls/version"
|
5
3
|
|
6
4
|
module Scrolls
|
@@ -8,33 +6,27 @@ module Scrolls
|
|
8
6
|
|
9
7
|
# Public: Initialize a Scrolls logger
|
10
8
|
#
|
11
|
-
# Convienence method to prepare for future releases. Currently mimics
|
12
|
-
# behavior found in other methods. This prepares the developer for a future
|
13
|
-
# backward incompatible change, see:
|
14
|
-
# https://github.com/asenchi/scrolls/pull/54
|
15
|
-
#
|
16
9
|
# options - A hash of key/values for configuring Scrolls
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
Log.single_line_exceptions = true
|
33
|
-
end
|
10
|
+
# stream - Stream to output data (default: STDOUT)
|
11
|
+
# log_facility - Syslog facility (default: Syslog::LOG_USER)
|
12
|
+
# time_unit - Unit of time (default: seconds)
|
13
|
+
# timestamp - Prepend logs with a timestamp (default: false)
|
14
|
+
# exceptions - Method for outputting exceptions (default: single line)
|
15
|
+
# global_context - Immutable context to prepend all messages with
|
16
|
+
# syslog_options - Syslog options (default: Syslog::LOG_PID|Syslog::LOG_CONS)
|
17
|
+
# escape_keys - Escape chars in keys
|
18
|
+
# strict_logfmt - Always use double quotes to quote values
|
19
|
+
#
|
20
|
+
def init(options={})
|
21
|
+
# Set a hint whether #init was called.
|
22
|
+
@initialized = true
|
23
|
+
@log = Logger.new(options)
|
24
|
+
end
|
34
25
|
|
35
|
-
|
36
|
-
|
37
|
-
|
26
|
+
# Public: Get the primary logger
|
27
|
+
#
|
28
|
+
def logger
|
29
|
+
@log.logger
|
38
30
|
end
|
39
31
|
|
40
32
|
# Public: Set a context in a block for logs
|
@@ -45,37 +37,13 @@ module Scrolls
|
|
45
37
|
# Examples:
|
46
38
|
#
|
47
39
|
def context(data, &blk)
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
# Deprecated: Get or set a global context that prefixs all logs
|
52
|
-
#
|
53
|
-
# data - A hash of key/values to prepend to each log
|
54
|
-
#
|
55
|
-
# This method will be deprecated two releases after 0.3.8.
|
56
|
-
# See https://github.com/asenchi/scrolls/releases/tag/v0.3.8
|
57
|
-
# for more details.
|
58
|
-
#
|
59
|
-
def global_context(data=nil)
|
60
|
-
$stderr.puts "global_context() will be deprecated after v0.3.8, please see https://github.com/asenchi/scrolls for more information."
|
61
|
-
if data
|
62
|
-
Log.global_context = data
|
63
|
-
else
|
64
|
-
Log.global_context
|
65
|
-
end
|
40
|
+
@log.with_context(data, &blk)
|
66
41
|
end
|
67
42
|
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# data - A hash of key/values to prepend to each log
|
71
|
-
#
|
72
|
-
# This method will be deprecated two releases after 0.3.8.
|
73
|
-
# See https://github.com/asenchi/scrolls/releases/tag/v0.3.8
|
74
|
-
# for more details.
|
43
|
+
# Public: Get the global context that prefixs all logs
|
75
44
|
#
|
76
|
-
def
|
77
|
-
|
78
|
-
Log.add_global_context(data)
|
45
|
+
def global_context
|
46
|
+
@log.global_context
|
79
47
|
end
|
80
48
|
|
81
49
|
# Public: Log data and/or wrap a block with start/finish
|
@@ -96,26 +64,32 @@ module Scrolls
|
|
96
64
|
# => nil
|
97
65
|
#
|
98
66
|
def log(data, &blk)
|
99
|
-
|
67
|
+
# Allows us to call #log directly and initialize defaults
|
68
|
+
@log = Logger.new({}) unless @initialized
|
69
|
+
|
70
|
+
@log.log(data, &blk)
|
100
71
|
end
|
101
72
|
|
102
73
|
# Public: Log an exception
|
103
74
|
#
|
104
|
-
# data - A hash of key/values to log
|
105
75
|
# e - An exception to pass to the logger
|
76
|
+
# data - A hash of key/values to log
|
106
77
|
#
|
107
78
|
# Examples:
|
108
79
|
#
|
109
80
|
# begin
|
110
81
|
# raise Exception
|
111
82
|
# rescue Exception => e
|
112
|
-
# Scrolls.log_exception({test: "test"}
|
83
|
+
# Scrolls.log_exception(e, {test: "test"})
|
113
84
|
# end
|
114
85
|
# test=test at=exception class=Exception message=Exception exception_id=70321999017240
|
115
86
|
# ...
|
116
87
|
#
|
117
|
-
def log_exception(
|
118
|
-
|
88
|
+
def log_exception(e, data)
|
89
|
+
# Allows us to call #log directly and initialize defaults
|
90
|
+
@log = Logger.new({}) unless @initialized
|
91
|
+
|
92
|
+
@log.log_exception(e, data)
|
119
93
|
end
|
120
94
|
|
121
95
|
# Public: Setup a logging facility (default: Syslog::LOG_USER)
|
@@ -127,7 +101,7 @@ module Scrolls
|
|
127
101
|
# Scrolls.facility = Syslog::LOG_LOCAL7
|
128
102
|
#
|
129
103
|
def facility=(f)
|
130
|
-
|
104
|
+
@log.facility=(f)
|
131
105
|
end
|
132
106
|
|
133
107
|
# Public: Return the Syslog facility
|
@@ -138,7 +112,7 @@ module Scrolls
|
|
138
112
|
# => 8
|
139
113
|
#
|
140
114
|
def facility
|
141
|
-
|
115
|
+
@log.facility
|
142
116
|
end
|
143
117
|
|
144
118
|
# Public: Setup a new output (default: STDOUT)
|
@@ -154,7 +128,7 @@ module Scrolls
|
|
154
128
|
# Scrolls.stream = StringIO.new
|
155
129
|
#
|
156
130
|
def stream=(out)
|
157
|
-
|
131
|
+
@log.stream=(out)
|
158
132
|
end
|
159
133
|
|
160
134
|
# Public: Return the stream
|
@@ -165,7 +139,7 @@ module Scrolls
|
|
165
139
|
# => #<IO:<STDOUT>>
|
166
140
|
#
|
167
141
|
def stream
|
168
|
-
|
142
|
+
@log.stream
|
169
143
|
end
|
170
144
|
|
171
145
|
# Public: Set the time unit we use for 'elapsed' (default: "seconds")
|
@@ -177,7 +151,7 @@ module Scrolls
|
|
177
151
|
# Scrolls.time_unit = "milliseconds"
|
178
152
|
#
|
179
153
|
def time_unit=(unit)
|
180
|
-
|
154
|
+
@log.time_unit = unit
|
181
155
|
end
|
182
156
|
|
183
157
|
# Public: Return the time unit currently configured
|
@@ -188,7 +162,7 @@ module Scrolls
|
|
188
162
|
# => "seconds"
|
189
163
|
#
|
190
164
|
def time_unit
|
191
|
-
|
165
|
+
@log.time_unit
|
192
166
|
end
|
193
167
|
|
194
168
|
# Public: Set whether to include a timestamp (now=<ISO8601>) field in the log
|
@@ -199,7 +173,7 @@ module Scrolls
|
|
199
173
|
# Scrolls.add_timestamp = true
|
200
174
|
#
|
201
175
|
def add_timestamp=(boolean)
|
202
|
-
|
176
|
+
@log.timestamp = boolean
|
203
177
|
end
|
204
178
|
|
205
179
|
# Public: Return whether the timestamp field will be included in the log
|
@@ -211,7 +185,7 @@ module Scrolls
|
|
211
185
|
# => true
|
212
186
|
#
|
213
187
|
def add_timestamp
|
214
|
-
|
188
|
+
@log.timestamp
|
215
189
|
end
|
216
190
|
|
217
191
|
# Public: Set whether exceptions should generate a single log
|
@@ -222,7 +196,7 @@ module Scrolls
|
|
222
196
|
# Scrolls.single_line_exceptions = true
|
223
197
|
#
|
224
198
|
def single_line_exceptions=(boolean)
|
225
|
-
|
199
|
+
@log.exceptions = boolean
|
226
200
|
end
|
227
201
|
|
228
202
|
# Public: Return whether exceptions generate a single log message.
|
@@ -233,7 +207,7 @@ module Scrolls
|
|
233
207
|
# => true
|
234
208
|
#
|
235
209
|
def single_line_exceptions?
|
236
|
-
|
210
|
+
@log.single_line_exceptions?
|
237
211
|
end
|
238
212
|
|
239
213
|
# Public: Convience method for Logger replacement
|
@@ -249,7 +223,7 @@ module Scrolls
|
|
249
223
|
#
|
250
224
|
def debug(data, &blk)
|
251
225
|
data = data.merge(:level => "debug") if data.is_a?(Hash)
|
252
|
-
|
226
|
+
@log.log(data, &blk)
|
253
227
|
end
|
254
228
|
|
255
229
|
# Public: Convience method for Logger replacement
|
@@ -267,7 +241,7 @@ module Scrolls
|
|
267
241
|
#
|
268
242
|
def error(data, &blk)
|
269
243
|
data = data.merge(:level => "warning") if data.is_a?(Hash)
|
270
|
-
|
244
|
+
@log.log(data, &blk)
|
271
245
|
end
|
272
246
|
|
273
247
|
# Public: Convience method for Logger replacement
|
@@ -285,7 +259,7 @@ module Scrolls
|
|
285
259
|
#
|
286
260
|
def fatal(data, &blk)
|
287
261
|
data = data.merge(:level => "error") if data.is_a?(Hash)
|
288
|
-
|
262
|
+
@log.log(data, &blk)
|
289
263
|
end
|
290
264
|
|
291
265
|
# Public: Convience method for Logger replacement
|
@@ -303,7 +277,7 @@ module Scrolls
|
|
303
277
|
#
|
304
278
|
def info(data, &blk)
|
305
279
|
data = data.merge(:level => "info") if data.is_a?(Hash)
|
306
|
-
|
280
|
+
@log.log(data, &blk)
|
307
281
|
end
|
308
282
|
|
309
283
|
# Public: Convience method for Logger replacement
|
@@ -321,7 +295,7 @@ module Scrolls
|
|
321
295
|
#
|
322
296
|
def warn(data, &blk)
|
323
297
|
data = data.merge(:level => "notice") if data.is_a?(Hash)
|
324
|
-
|
298
|
+
@log.log(data, &blk)
|
325
299
|
end
|
326
300
|
|
327
301
|
# Public: Convience method for Logger replacement
|
@@ -339,7 +313,13 @@ module Scrolls
|
|
339
313
|
#
|
340
314
|
def unknown(data, &blk)
|
341
315
|
data = data.merge(:level => "alert") if data.is_a?(Hash)
|
342
|
-
|
316
|
+
@log.log(data, &blk)
|
317
|
+
end
|
318
|
+
|
319
|
+
# Internal: The Logger initialized by #init
|
320
|
+
#
|
321
|
+
def internal
|
322
|
+
@log
|
343
323
|
end
|
344
324
|
|
345
325
|
end
|
data/test/test_helper.rb
CHANGED
data/test/test_parser.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
2
2
|
|
3
|
-
class TestScrollsParser < Test
|
3
|
+
class TestScrollsParser < Minitest::Test
|
4
4
|
include Scrolls::Parser
|
5
5
|
|
6
6
|
def test_parse_bool
|
@@ -79,6 +79,21 @@ class TestScrollsParser < Test::Unit::TestCase
|
|
79
79
|
assert_equal 't="2012-06-19T16:02:35+01:00"', unparse(data)
|
80
80
|
end
|
81
81
|
|
82
|
+
def test_unparse_escape_keys
|
83
|
+
html = "<p>p</p>"
|
84
|
+
slash = "p/p"
|
85
|
+
|
86
|
+
data = { html => "d", slash => "d" }
|
87
|
+
assert_equal '<p>p</p>=d p/p=d',
|
88
|
+
unparse(data, escape_keys=true)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_unparse_strict_logfmt
|
92
|
+
data = { s: 'echo "hello"' }
|
93
|
+
assert_equal 's="echo \"hello\""', unparse(data, escape_keys=false, strict_logfmt=true)
|
94
|
+
assert_equal data.inspect, parse(unparse(data, escape_keys=false, strict_logfmt=true)).inspect
|
95
|
+
end
|
96
|
+
|
82
97
|
def test_parse_time
|
83
98
|
time = Time.new(2012, 06, 19, 16, 02, 35, "+01:00")
|
84
99
|
string = "t=2012-06-19T16:02:35+01:00"
|
data/test/test_scrolls.rb
CHANGED
@@ -1,44 +1,35 @@
|
|
1
|
-
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
2
2
|
|
3
|
-
class TestScrolls < Test
|
3
|
+
class TestScrolls < Minitest::Test
|
4
4
|
def setup
|
5
5
|
@out = StringIO.new
|
6
|
-
Scrolls.init(
|
7
|
-
|
8
|
-
|
9
|
-
def teardown
|
10
|
-
Scrolls.global_context({})
|
11
|
-
# Reset our syslog context
|
12
|
-
Scrolls.facility = Scrolls::LOG_FACILITY
|
13
|
-
Scrolls.add_timestamp = false
|
6
|
+
Scrolls.init(
|
7
|
+
:stream => @out
|
8
|
+
)
|
14
9
|
end
|
15
10
|
|
16
|
-
def
|
17
|
-
|
11
|
+
def test_default_construct
|
12
|
+
Scrolls.init
|
13
|
+
assert_equal Scrolls::IOLogger, Scrolls.logger.class
|
18
14
|
end
|
19
15
|
|
20
16
|
def test_default_global_context
|
17
|
+
Scrolls.init(:stream => @out)
|
21
18
|
assert_equal Hash.new, Scrolls.global_context
|
22
19
|
end
|
23
20
|
|
24
21
|
def test_setting_global_context
|
25
|
-
Scrolls.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_adding_to_global_context
|
32
|
-
Scrolls.global_context(:g => "g")
|
33
|
-
Scrolls.add_global_context(:h => "h")
|
22
|
+
Scrolls.init(
|
23
|
+
:stream => @out,
|
24
|
+
:global_context => {:g => "g"},
|
25
|
+
)
|
34
26
|
Scrolls.log(:d => "d")
|
35
|
-
|
36
|
-
assert_match /g=g.*h=h.*d=d/, global
|
27
|
+
assert_equal "g=g d=d\n", @out.string
|
37
28
|
end
|
38
29
|
|
39
30
|
def test_default_context
|
40
|
-
Scrolls.log(:
|
41
|
-
assert_equal Hash.new, Scrolls
|
31
|
+
Scrolls.log(:d => "d")
|
32
|
+
assert_equal Hash.new, Scrolls.internal.context
|
42
33
|
end
|
43
34
|
|
44
35
|
def test_setting_context
|
@@ -48,15 +39,19 @@ class TestScrolls < Test::Unit::TestCase
|
|
48
39
|
end
|
49
40
|
|
50
41
|
def test_all_the_contexts
|
51
|
-
Scrolls.
|
42
|
+
Scrolls.init(
|
43
|
+
:stream => @out,
|
44
|
+
:global_context => {:g => "g"},
|
45
|
+
)
|
52
46
|
Scrolls.log(:o => "o") do
|
53
47
|
Scrolls.context(:c => "c") do
|
54
48
|
Scrolls.log(:ic => "i")
|
55
49
|
end
|
56
50
|
Scrolls.log(:i => "i")
|
57
51
|
end
|
58
|
-
|
59
|
-
|
52
|
+
@out.truncate(37)
|
53
|
+
output = "g=g o=o at=start\ng=g c=c ic=i\ng=g i=i"
|
54
|
+
assert_equal output, @out.string
|
60
55
|
end
|
61
56
|
|
62
57
|
def test_deeply_nested_context
|
@@ -89,12 +84,27 @@ class TestScrolls < Test::Unit::TestCase
|
|
89
84
|
raise "Error from inside of context"
|
90
85
|
end
|
91
86
|
fail "Exception did not escape context block"
|
92
|
-
rescue
|
87
|
+
rescue
|
93
88
|
Scrolls.log(:o => 'o')
|
94
89
|
assert_equal "o=o\n", @out.string
|
95
90
|
end
|
96
91
|
end
|
97
92
|
|
93
|
+
def test_deeply_nested_context_after_exception
|
94
|
+
Scrolls.log(:o => "o") do
|
95
|
+
begin
|
96
|
+
Scrolls.log(:io => 'io') do
|
97
|
+
raise "Error from inside of nested logging"
|
98
|
+
end
|
99
|
+
rescue
|
100
|
+
Scrolls.log(:o => 'o')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
@out.truncate(124)
|
104
|
+
output = "o=o at=start\nio=io at=start\nio=io at=exception reraise=true class=RuntimeError message=\"Error from inside of nested logging\""
|
105
|
+
assert_equal output, @out.string
|
106
|
+
end
|
107
|
+
|
98
108
|
def test_default_time_unit
|
99
109
|
assert_equal "seconds", Scrolls.time_unit
|
100
110
|
end
|
@@ -105,8 +115,15 @@ class TestScrolls < Test::Unit::TestCase
|
|
105
115
|
end
|
106
116
|
|
107
117
|
def test_setting_incorrect_time_unit
|
108
|
-
|
118
|
+
assert_raises Scrolls::TimeUnitError do
|
109
119
|
Scrolls.time_unit = "years"
|
120
|
+
Scrolls.log(:tu => "yrs")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_unknown_log_level
|
125
|
+
assert_raises Scrolls::LogLevelError do
|
126
|
+
Scrolls.log(:level => "nope")
|
110
127
|
end
|
111
128
|
end
|
112
129
|
|
@@ -125,28 +142,28 @@ class TestScrolls < Test::Unit::TestCase
|
|
125
142
|
begin
|
126
143
|
raise Exception
|
127
144
|
rescue Exception => e
|
128
|
-
Scrolls.log_exception({:test => "exception"}
|
145
|
+
Scrolls.log_exception(e, {:test => "exception"})
|
129
146
|
end
|
130
147
|
|
131
|
-
|
132
|
-
|
133
|
-
assert_match /test=exception at=exception.*test_log_exception.*XX/,
|
134
|
-
oneline_backtrace
|
148
|
+
oneline_bt = @out.string.gsub("\n", 'XX')
|
149
|
+
assert_match(/test=exception at=exception.*test_log_exception.*XX/, oneline_bt)
|
135
150
|
end
|
136
151
|
|
137
|
-
def
|
138
|
-
Scrolls.single_line_exceptions =
|
152
|
+
def test_multi_line_exceptions
|
153
|
+
Scrolls.single_line_exceptions = "multi"
|
139
154
|
begin
|
140
155
|
raise Exception
|
141
156
|
rescue Exception => e
|
142
|
-
Scrolls.log_exception({:o => "o"}
|
157
|
+
Scrolls.log_exception(e, {:o => "o"})
|
143
158
|
end
|
144
|
-
|
159
|
+
|
160
|
+
oneline_bt = @out.string.gsub("\n", 'XX')
|
161
|
+
assert_match(/o=o at=exception.*test_multi_line_exceptions.*XX/, oneline_bt)
|
145
162
|
end
|
146
163
|
|
147
164
|
def test_syslog_integration
|
148
165
|
Scrolls.stream = 'syslog'
|
149
|
-
assert_equal Scrolls::SyslogLogger, Scrolls.
|
166
|
+
assert_equal Scrolls::SyslogLogger, Scrolls.internal.logger.class
|
150
167
|
end
|
151
168
|
|
152
169
|
def test_syslog_facility
|
@@ -162,13 +179,7 @@ class TestScrolls < Test::Unit::TestCase
|
|
162
179
|
def test_setting_syslog_facility_after_instantiation
|
163
180
|
Scrolls.stream = 'syslog'
|
164
181
|
Scrolls.facility = 'local7'
|
165
|
-
assert_match
|
166
|
-
end
|
167
|
-
|
168
|
-
def test_logging_message_with_syslog
|
169
|
-
Scrolls.stream = 'syslog'
|
170
|
-
Scrolls.facility = 'local7'
|
171
|
-
Scrolls.log "scrolls test"
|
182
|
+
assert_match(/facility=184/, Scrolls.internal.logger.inspect)
|
172
183
|
end
|
173
184
|
|
174
185
|
def test_add_timestamp
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scrolls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Curt Micol
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Logging, easier, more consistent.
|
14
14
|
email:
|
@@ -25,15 +25,13 @@ files:
|
|
25
25
|
- docs/global-context.md
|
26
26
|
- docs/syslog.md
|
27
27
|
- lib/scrolls.rb
|
28
|
-
- lib/scrolls/
|
29
|
-
- lib/scrolls/
|
30
|
-
- lib/scrolls/log.rb
|
28
|
+
- lib/scrolls/iologger.rb
|
29
|
+
- lib/scrolls/logger.rb
|
31
30
|
- lib/scrolls/parser.rb
|
32
|
-
- lib/scrolls/
|
31
|
+
- lib/scrolls/sysloglogger.rb
|
33
32
|
- lib/scrolls/utils.rb
|
34
33
|
- lib/scrolls/version.rb
|
35
34
|
- scrolls.gemspec
|
36
|
-
- test/test_atomic.rb
|
37
35
|
- test/test_helper.rb
|
38
36
|
- test/test_parser.rb
|
39
37
|
- test/test_scrolls.rb
|
@@ -56,13 +54,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
54
|
- !ruby/object:Gem::Version
|
57
55
|
version: '0'
|
58
56
|
requirements: []
|
59
|
-
|
60
|
-
rubygems_version: 2.6.11
|
57
|
+
rubygems_version: 3.2.29
|
61
58
|
signing_key:
|
62
59
|
specification_version: 4
|
63
60
|
summary: When do we log? All the time.
|
64
61
|
test_files:
|
65
|
-
- test/test_atomic.rb
|
66
62
|
- test/test_helper.rb
|
67
63
|
- test/test_parser.rb
|
68
64
|
- test/test_scrolls.rb
|
data/lib/scrolls/atomic.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
module Scrolls
|
4
|
-
# The result of issues with an update I made to Scrolls. After talking with
|
5
|
-
# Fabio Kung about a fix I started work on an atomic object, but he added some
|
6
|
-
# fixes to #context without it and then used Headius' atomic gem.
|
7
|
-
#
|
8
|
-
# The code below is the start and cleanup of my atomic object. It's slim on
|
9
|
-
# details and eventually cleaned up around inspiration from Headius' code.
|
10
|
-
#
|
11
|
-
# LICENSE: Apache 2.0
|
12
|
-
#
|
13
|
-
# See Headius' atomic gem here:
|
14
|
-
# https://github.com/headius/ruby-atomic
|
15
|
-
class AtomicObject
|
16
|
-
def initialize(o)
|
17
|
-
@mtx = Mutex.new
|
18
|
-
@o = o
|
19
|
-
end
|
20
|
-
|
21
|
-
def get
|
22
|
-
@mtx.synchronize { @o }
|
23
|
-
end
|
24
|
-
|
25
|
-
def set(n)
|
26
|
-
@mtx.synchronize { @o = n }
|
27
|
-
end
|
28
|
-
|
29
|
-
def verify_set(o, n)
|
30
|
-
return false unless @mtx.try_lock
|
31
|
-
begin
|
32
|
-
return false unless @o.equal? o
|
33
|
-
@o = n
|
34
|
-
ensure
|
35
|
-
@mtx.unlock
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class Atomic < AtomicObject
|
41
|
-
def initialize(v=nil)
|
42
|
-
super(v)
|
43
|
-
end
|
44
|
-
|
45
|
-
def value
|
46
|
-
self.get
|
47
|
-
end
|
48
|
-
|
49
|
-
def value=(v)
|
50
|
-
self.set(v)
|
51
|
-
v
|
52
|
-
end
|
53
|
-
|
54
|
-
def update
|
55
|
-
true until self.verify_set(o = self.get, n = yield(o))
|
56
|
-
n
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|