sidekiq-unique-jobs 7.0.0.beta2 → 7.0.0.beta3
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.
Potentially problematic release.
This version of sidekiq-unique-jobs might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +6 -6
- data/lib/sidekiq_unique_jobs.rb +1 -1
- data/lib/sidekiq_unique_jobs/exceptions.rb +0 -83
- data/lib/sidekiq_unique_jobs/lock/until_expired.rb +5 -0
- data/lib/sidekiq_unique_jobs/orphans/manager.rb +2 -2
- data/lib/sidekiq_unique_jobs/orphans/reaper.rb +37 -5
- data/lib/sidekiq_unique_jobs/script.rb +4 -121
- data/lib/sidekiq_unique_jobs/script/caller.rb +1 -1
- data/lib/sidekiq_unique_jobs/version.rb +1 -1
- metadata +24 -5
- data/lib/sidekiq_unique_jobs/script/template.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5f537750acf3b6a7b8f25ede43519210cc05dc77069417539a54c0c2d0c114c
|
4
|
+
data.tar.gz: 367d2a7f27d10200d4eb2b148b2ea34fbdffe16eb52ae71cfe73b5b20d2822d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fe2296811e1d1d8350c51d232261e61879317a6a4c46a86a302dfac9a0ad341191086ac96db74430d51ead315e370f1073f6015098fff09d5995abcc40d5146
|
7
|
+
data.tar.gz: 6fd909cfb0c8960cc1cb14bbd336493897121d24801ad1c2b678733666fba76a3ea0a5d6868e814c9f426080ff027fdf6102ffee08a2108e2ee840496a493717
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v7.0.0.beta2](https://github.com/mhenrixon/sidekiq-unique-jobs/tree/v7.0.0.beta2) (2019-10-08)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v7.0.0.beta1...v7.0.0.beta2)
|
6
|
+
|
7
|
+
**Fixed bugs:**
|
8
|
+
|
9
|
+
- Pass redis\_version into scripts [\#431](https://github.com/mhenrixon/sidekiq-unique-jobs/pull/431) ([mhenrixon](https://github.com/mhenrixon))
|
10
|
+
|
11
|
+
**Closed issues:**
|
12
|
+
|
13
|
+
- incorrect `:until\_and\_while\_executing` behavior [\#424](https://github.com/mhenrixon/sidekiq-unique-jobs/issues/424)
|
14
|
+
|
3
15
|
## [v7.0.0.beta1](https://github.com/mhenrixon/sidekiq-unique-jobs/tree/v7.0.0.beta1) (2019-10-07)
|
4
16
|
|
5
17
|
[Full Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v6.0.15...v7.0.0.beta1)
|
data/README.md
CHANGED
@@ -418,7 +418,7 @@ The last one is log which can be be used with the lock `UntilExecuted` and `Unti
|
|
418
418
|
### log
|
419
419
|
|
420
420
|
```ruby
|
421
|
-
sidekiq_options on_conflict: :log
|
421
|
+
sidekiq_options on_conflict: :log
|
422
422
|
```
|
423
423
|
|
424
424
|
This strategy is intended to be used with `UntilExecuted` and `UntilExpired`. It will log a line about that this is job is a duplicate of another.
|
@@ -426,7 +426,7 @@ This strategy is intended to be used with `UntilExecuted` and `UntilExpired`. It
|
|
426
426
|
### raise
|
427
427
|
|
428
428
|
```ruby
|
429
|
-
sidekiq_options on_conflict: :raise
|
429
|
+
sidekiq_options on_conflict: :raise
|
430
430
|
```
|
431
431
|
|
432
432
|
This strategy is intended to be used with `WhileExecuting`. Basically it will allow us to let the server process crash with a specific error message and be retried without messing up the Sidekiq stats.
|
@@ -434,7 +434,7 @@ This strategy is intended to be used with `WhileExecuting`. Basically it will al
|
|
434
434
|
### reject
|
435
435
|
|
436
436
|
```ruby
|
437
|
-
sidekiq_options on_conflict: :reject
|
437
|
+
sidekiq_options on_conflict: :reject
|
438
438
|
```
|
439
439
|
|
440
440
|
This strategy is intended to be used with `WhileExecuting` and will push the job to the dead queue on conflict.
|
@@ -442,7 +442,7 @@ This strategy is intended to be used with `WhileExecuting` and will push the job
|
|
442
442
|
### replace
|
443
443
|
|
444
444
|
```ruby
|
445
|
-
sidekiq_options on_conflict: :replace
|
445
|
+
sidekiq_options on_conflict: :replace
|
446
446
|
```
|
447
447
|
|
448
448
|
This strategy is intended to be used with client locks like `UntilExecuted`.
|
@@ -455,7 +455,7 @@ always scheduled in the future. Currently only attempting to retry one time.
|
|
455
455
|
### Reschedule
|
456
456
|
|
457
457
|
```ruby
|
458
|
-
sidekiq_options on_conflict: :reschedule
|
458
|
+
sidekiq_options on_conflict: :reschedule
|
459
459
|
```
|
460
460
|
|
461
461
|
This strategy is intended to be used with `WhileExecuting` and will delay the job to be tried again in 5 seconds. This will mess up the sidekiq stats but will prevent exceptions from being logged and confuse your sysadmins.
|
@@ -475,7 +475,7 @@ module Strategies
|
|
475
475
|
end
|
476
476
|
```
|
477
477
|
|
478
|
-
You can refer
|
478
|
+
You can refer to all the strategies defined in `lib/sidekiq_unique_jobs/on_conflict`.
|
479
479
|
|
480
480
|
In order to make it available, you should call in your project startup:
|
481
481
|
|
data/lib/sidekiq_unique_jobs.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "brpoplpush/redis_script"
|
3
4
|
require "concurrent/future"
|
4
5
|
require "concurrent/promises"
|
5
6
|
require "concurrent/timer_task"
|
@@ -25,7 +26,6 @@ require "sidekiq_unique_jobs/connection"
|
|
25
26
|
require "sidekiq_unique_jobs/exceptions"
|
26
27
|
require "sidekiq_unique_jobs/script"
|
27
28
|
require "sidekiq_unique_jobs/script/caller"
|
28
|
-
require "sidekiq_unique_jobs/script/template"
|
29
29
|
require "sidekiq_unique_jobs/json"
|
30
30
|
require "sidekiq_unique_jobs/normalizer"
|
31
31
|
require "sidekiq_unique_jobs/job"
|
@@ -82,89 +82,6 @@ module SidekiqUniqueJobs
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
-
# Error raised from {OnConflict::Raise}
|
86
|
-
#
|
87
|
-
# @author Mikael Henriksson <mikael@zoolutions.se>
|
88
|
-
class ScriptError < UniqueJobsError
|
89
|
-
# Reformats errors raised by redis representing failures while executing
|
90
|
-
# a lua script. The default errors have confusing messages and backtraces,
|
91
|
-
# and a type of +RuntimeError+. This class improves the message and
|
92
|
-
# modifies the backtrace to include the lua script itself in a reasonable
|
93
|
-
# way.
|
94
|
-
|
95
|
-
PATTERN = /ERR Error (compiling|running) script \(.*?\): .*?:(\d+): (.*)/.freeze
|
96
|
-
LIB_PATH = File.expand_path("..", __dir__)
|
97
|
-
CONTEXT_LINE_NUMBER = 3
|
98
|
-
|
99
|
-
attr_reader :error, :file, :content
|
100
|
-
|
101
|
-
# Is this error one that should be reformatted?
|
102
|
-
#
|
103
|
-
# @param error [StandardError] the original error raised by redis
|
104
|
-
# @return [Boolean] is this an error that should be reformatted?
|
105
|
-
def self.intercepts?(error)
|
106
|
-
error.message =~ PATTERN
|
107
|
-
end
|
108
|
-
|
109
|
-
# Initialize a new {ScriptError} from an existing redis error, adjusting
|
110
|
-
# the message and backtrace in the process.
|
111
|
-
#
|
112
|
-
# @param error [StandardError] the original error raised by redis
|
113
|
-
# @param file [Pathname] full path to the lua file the error ocurred in
|
114
|
-
# @param content [String] lua file content the error ocurred in
|
115
|
-
# :nocov:
|
116
|
-
def initialize(error, file, content)
|
117
|
-
@error = error
|
118
|
-
@file = file
|
119
|
-
@content = content
|
120
|
-
@backtrace = @error.backtrace
|
121
|
-
|
122
|
-
@error.message.match(PATTERN) do |regexp_match|
|
123
|
-
line_number = regexp_match[2].to_i
|
124
|
-
message = regexp_match[3]
|
125
|
-
error_context = generate_error_context(content, line_number)
|
126
|
-
|
127
|
-
super("#{message}\n\n#{error_context}\n\n")
|
128
|
-
set_backtrace(generate_backtrace(file, line_number))
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
private
|
133
|
-
|
134
|
-
# :nocov:
|
135
|
-
def generate_error_context(content, line_number)
|
136
|
-
lines = content.lines.to_a
|
137
|
-
beginning_line_number = [1, line_number - CONTEXT_LINE_NUMBER].max
|
138
|
-
ending_line_number = [lines.count, line_number + CONTEXT_LINE_NUMBER].min
|
139
|
-
line_number_width = ending_line_number.to_s.length
|
140
|
-
|
141
|
-
(beginning_line_number..ending_line_number).map do |number|
|
142
|
-
indicator = (number == line_number) ? "=>" : " "
|
143
|
-
formatted_number = format("%#{line_number_width}d", number)
|
144
|
-
" #{indicator} #{formatted_number}: #{lines[number - 1]}"
|
145
|
-
end.join.chomp
|
146
|
-
end
|
147
|
-
|
148
|
-
# :nocov:
|
149
|
-
def generate_backtrace(file, line_number)
|
150
|
-
pre_gem = backtrace_before_entering_gem(@backtrace)
|
151
|
-
index_of_first_unique_jobs_line = (@backtrace.size - pre_gem.size - 1)
|
152
|
-
pre_gem.unshift(@backtrace[index_of_first_unique_jobs_line])
|
153
|
-
pre_gem.unshift("#{file}:#{line_number}")
|
154
|
-
pre_gem
|
155
|
-
end
|
156
|
-
|
157
|
-
# :nocov:
|
158
|
-
def backtrace_before_entering_gem(backtrace)
|
159
|
-
backtrace.reverse.take_while { |line| !line_from_gem(line) }.reverse
|
160
|
-
end
|
161
|
-
|
162
|
-
# :nocov:
|
163
|
-
def line_from_gem(line)
|
164
|
-
line.split(":").first.include?(LIB_PATH)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
85
|
# Error raised from {OptionsWithFallback#lock_class}
|
169
86
|
#
|
170
87
|
# @author Mikael Henriksson <mikael@zoolutions.se>
|
@@ -19,7 +19,7 @@ module SidekiqUniqueJobs
|
|
19
19
|
#
|
20
20
|
def self.start
|
21
21
|
with_logging_context do
|
22
|
-
|
22
|
+
log_info("Starting Reaper")
|
23
23
|
task.add_observer(Observer.new)
|
24
24
|
task.execute
|
25
25
|
task
|
@@ -34,7 +34,7 @@ module SidekiqUniqueJobs
|
|
34
34
|
#
|
35
35
|
def self.stop
|
36
36
|
with_logging_context do
|
37
|
-
|
37
|
+
log_info("Stopping Reaper")
|
38
38
|
task.shutdown
|
39
39
|
end
|
40
40
|
end
|
@@ -175,11 +175,43 @@ module SidekiqUniqueJobs
|
|
175
175
|
#
|
176
176
|
#
|
177
177
|
def enqueued?(digest)
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
178
|
+
Sidekiq.redis do |conn|
|
179
|
+
queues(conn) do |queue|
|
180
|
+
entries(conn, queue) do |entry|
|
181
|
+
if entry.include?(digest)
|
182
|
+
log_info("#{digest} found in #{queue}")
|
183
|
+
return true
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
log_info("#{digest} not enqueued")
|
189
|
+
false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def queues(conn, &block)
|
194
|
+
conn.sscan_each("queues", &block)
|
195
|
+
end
|
196
|
+
|
197
|
+
def entries(conn, queue) # rubocop:disable Metrics/MethodLength
|
198
|
+
queue_key = "queue:#{queue}"
|
199
|
+
initial_size = conn.llen(queue_key)
|
200
|
+
deleted_size = 0
|
201
|
+
page = 0
|
202
|
+
page_size = 50
|
203
|
+
|
204
|
+
loop do
|
205
|
+
range_start = page * page_size - deleted_size
|
206
|
+
range_end = range_start + page_size - 1
|
207
|
+
entries = conn.lrange(queue_key, range_start, range_end)
|
208
|
+
page += 1
|
209
|
+
|
210
|
+
entries.each do |entry|
|
211
|
+
yield entry
|
212
|
+
end
|
213
|
+
|
214
|
+
deleted_size = initial_size - size
|
183
215
|
end
|
184
216
|
end
|
185
217
|
|
@@ -5,128 +5,11 @@ module SidekiqUniqueJobs
|
|
5
5
|
#
|
6
6
|
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
7
|
module Script
|
8
|
-
|
9
|
-
SCRIPT_SHAS ||= Concurrent::Map.new
|
8
|
+
include Brpoplpush::RedisScript::DSL
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
module_function
|
16
|
-
|
17
|
-
#
|
18
|
-
# Call a lua script with the provided file_name
|
19
|
-
#
|
20
|
-
# @note this method is recursive if we need to load a lua script
|
21
|
-
# that wasn't previously loaded.
|
22
|
-
#
|
23
|
-
# @param [Symbol] file_name the name of the lua script
|
24
|
-
# @param [Array<String>] keys script keys
|
25
|
-
# @param [Array<Object>] argv script arguments
|
26
|
-
# @param [Redis] conn the redis connection to use
|
27
|
-
#
|
28
|
-
# @return value from script
|
29
|
-
#
|
30
|
-
def call(file_name, conn, keys: [], argv: [])
|
31
|
-
result, elapsed = timed do
|
32
|
-
execute_script(file_name, conn, keys, argv)
|
33
|
-
end
|
34
|
-
|
35
|
-
log_debug("Executed #{file_name}.lua in #{elapsed}ms")
|
36
|
-
result
|
37
|
-
rescue ::Redis::CommandError => ex
|
38
|
-
handle_error(ex, file_name, conn) do
|
39
|
-
call(file_name, conn, keys: keys, argv: argv)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
#
|
44
|
-
# Execute the script file
|
45
|
-
#
|
46
|
-
# @param [Symbol] file_name the name of the lua script
|
47
|
-
# @param [Redis] conn the redis connection to use
|
48
|
-
# @param [Array] keys the array of keys to pass to the script
|
49
|
-
# @param [Array] argv the array of arguments to pass to the script
|
50
|
-
#
|
51
|
-
# @return value from script (evalsha)
|
52
|
-
#
|
53
|
-
def execute_script(file_name, conn, keys, argv)
|
54
|
-
conn.evalsha(
|
55
|
-
script_sha(conn, file_name),
|
56
|
-
keys,
|
57
|
-
argv,
|
58
|
-
)
|
59
|
-
end
|
60
|
-
|
61
|
-
#
|
62
|
-
# Return sha of already loaded lua script or load it and return the sha
|
63
|
-
#
|
64
|
-
# @param [Sidekiq::RedisConnection] conn the redis connection
|
65
|
-
# @param [Symbol] file_name the name of the lua script
|
66
|
-
# @return [String] sha of the script file
|
67
|
-
#
|
68
|
-
# @return [String] the sha of the script
|
69
|
-
#
|
70
|
-
def script_sha(conn, file_name)
|
71
|
-
if (sha = SCRIPT_SHAS.get(file_name))
|
72
|
-
return sha
|
73
|
-
end
|
74
|
-
|
75
|
-
sha = conn.script(:load, script_source(file_name))
|
76
|
-
SCRIPT_SHAS.put(file_name, sha)
|
77
|
-
sha
|
78
|
-
end
|
79
|
-
|
80
|
-
#
|
81
|
-
# Handle errors to allow retrying errors that need retrying
|
82
|
-
#
|
83
|
-
# @param [Redis::CommandError] ex exception to handle
|
84
|
-
# @param [Symbol] file_name the name of the lua script
|
85
|
-
# @param [Redis] conn the redis connection to use
|
86
|
-
#
|
87
|
-
# @return [void]
|
88
|
-
#
|
89
|
-
# @yieldreturn [void] yields back to the caller when NOSCRIPT is raised
|
90
|
-
def handle_error(ex, file_name, conn) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
91
|
-
case ex.message
|
92
|
-
when "NOSCRIPT No matching script. Please use EVAL."
|
93
|
-
SCRIPT_SHAS.delete(file_name)
|
94
|
-
return yield if block_given?
|
95
|
-
when "BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE."
|
96
|
-
begin
|
97
|
-
conn.script(:kill)
|
98
|
-
return yield if block_given?
|
99
|
-
rescue ::Redis::CommandError => ex
|
100
|
-
log_warn(ex)
|
101
|
-
return yield if block_given?
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
raise unless ScriptError.intercepts?(ex)
|
106
|
-
|
107
|
-
raise ScriptError.new(ex, script_path(file_name).to_s, script_source(file_name))
|
108
|
-
end
|
109
|
-
|
110
|
-
#
|
111
|
-
# Reads the lua file from disk
|
112
|
-
#
|
113
|
-
# @param [Symbol] file_name the name of the lua script
|
114
|
-
#
|
115
|
-
# @return [String] the content of the lua file
|
116
|
-
#
|
117
|
-
def script_source(file_name)
|
118
|
-
Template.new(LUA_PATHNAME).render(script_path(file_name))
|
119
|
-
end
|
120
|
-
|
121
|
-
#
|
122
|
-
# Construct a Pathname to a lua script
|
123
|
-
#
|
124
|
-
# @param [Symbol] file_name the name of the lua script
|
125
|
-
#
|
126
|
-
# @return [Pathname] the full path to the gems lua script
|
127
|
-
#
|
128
|
-
def script_path(file_name)
|
129
|
-
LUA_PATHNAME.join("#{file_name}.lua")
|
10
|
+
configure do |config|
|
11
|
+
config.scripts_path = Pathname.new(__FILE__).dirname.join("lua")
|
12
|
+
config.logger = Sidekiq.logger # TODO: This becomes a little weird
|
130
13
|
end
|
131
14
|
end
|
132
15
|
end
|
metadata
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-unique-jobs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.0.
|
4
|
+
version: 7.0.0.beta3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikael Henriksson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: brpoplpush-redis_script
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.0
|
20
|
+
- - "<="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.0.0
|
30
|
+
- - "<="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.0
|
13
33
|
- !ruby/object:Gem::Dependency
|
14
34
|
name: concurrent-ruby
|
15
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -309,7 +329,6 @@ files:
|
|
309
329
|
- lib/sidekiq_unique_jobs/rspec/matchers/have_valid_sidekiq_options.rb
|
310
330
|
- lib/sidekiq_unique_jobs/script.rb
|
311
331
|
- lib/sidekiq_unique_jobs/script/caller.rb
|
312
|
-
- lib/sidekiq_unique_jobs/script/template.rb
|
313
332
|
- lib/sidekiq_unique_jobs/sidekiq_unique_ext.rb
|
314
333
|
- lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb
|
315
334
|
- lib/sidekiq_unique_jobs/sidekiq_worker_methods.rb
|
@@ -345,14 +364,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
345
364
|
requirements:
|
346
365
|
- - ">="
|
347
366
|
- !ruby/object:Gem::Version
|
348
|
-
version:
|
367
|
+
version: 2.5.0
|
349
368
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
350
369
|
requirements:
|
351
370
|
- - ">"
|
352
371
|
- !ruby/object:Gem::Version
|
353
372
|
version: 1.3.1
|
354
373
|
requirements: []
|
355
|
-
rubygems_version: 3.0.
|
374
|
+
rubygems_version: 3.0.3
|
356
375
|
signing_key:
|
357
376
|
specification_version: 4
|
358
377
|
summary: Sidekiq middleware that prevents duplicates jobs
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SidekiqUniqueJobs
|
4
|
-
# Interface to dealing with .lua files
|
5
|
-
#
|
6
|
-
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
-
module Script
|
8
|
-
#
|
9
|
-
# Class Template provides LUA script partial template rendering
|
10
|
-
#
|
11
|
-
# @author Mikael Henriksson <mikael@zoolutions.se>
|
12
|
-
#
|
13
|
-
class Template
|
14
|
-
def initialize(script_path)
|
15
|
-
@script_path = script_path
|
16
|
-
end
|
17
|
-
|
18
|
-
#
|
19
|
-
# Renders a Lua script and includes any partials in that file
|
20
|
-
# all `<%= include_partial '' %>` replaced with the actual contents of the partial
|
21
|
-
#
|
22
|
-
# @param [Pathname] pathname the path to the
|
23
|
-
#
|
24
|
-
# @return [String] the rendered Luascript
|
25
|
-
#
|
26
|
-
def render(pathname)
|
27
|
-
@partial_templates ||= {}
|
28
|
-
ERB.new(File.read(pathname)).result(binding)
|
29
|
-
end
|
30
|
-
|
31
|
-
# helper method to include a lua partial within another lua script
|
32
|
-
#
|
33
|
-
def include_partial(relative_path)
|
34
|
-
return if @partial_templates.key?(relative_path)
|
35
|
-
|
36
|
-
@partial_templates[relative_path] = nil
|
37
|
-
render(Pathname.new("#{@script_path}/#{relative_path}"))
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|