exedb 0.0.3 → 0.1.1
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.
- checksums.yaml +4 -4
- data/lib/exedb/version.rb +1 -1
- data/lib/exedb.rb +109 -30
- data/spec/exedb_spec.rb +37 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2edd3f5d079de4f4fe759bc639c12848fdc1b384
|
4
|
+
data.tar.gz: ea2957752bc6856ed29bc50a1813caa977a46bf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb50137af58069d48b51c058f876e268ba46913ce5c0ce1b57a39ad2892ae3919775ee21f42ad9858df3177406ffa098e8e97bc41e45db882b1273866ed39b90
|
7
|
+
data.tar.gz: d1dcc865f0751ed9115334b9cd6751c532a63f4c839c6b47d9747e0c5a58a93da4f1c6c2b273fb9d7a5f84eb0c5f86d1c06f62f5e80c0a9cbf83c61812123c54
|
data/lib/exedb/version.rb
CHANGED
data/lib/exedb.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
require 'digest'
|
2
2
|
require 'time'
|
3
3
|
|
4
|
+
#
|
5
|
+
# Database-like interface for long-running tasks.
|
6
|
+
#
|
7
|
+
# Each instance can run single command (get).
|
8
|
+
# If two or more instances with the same command do 'get', then only first
|
9
|
+
# will really execute command, all others will wait
|
10
|
+
# for result (flock is used).
|
11
|
+
#
|
12
|
+
# Results of command execution (stdout) is cached. Next 'get'
|
13
|
+
# will return cached results (unless cache timeout happened).
|
14
|
+
#
|
15
|
+
# You can force execution, calling 'update' method.
|
16
|
+
#
|
17
|
+
# Exit code is available via 'code' method
|
18
|
+
#
|
4
19
|
class Exedb
|
5
20
|
|
6
21
|
SLEEP_TIME=1
|
@@ -10,26 +25,49 @@ class Exedb
|
|
10
25
|
attr_accessor :cache_timeout, :cache_dir
|
11
26
|
attr_reader :update_time
|
12
27
|
|
28
|
+
# Constructor
|
29
|
+
# @str - command to be executed
|
30
|
+
#
|
13
31
|
def initialize(str='')
|
14
32
|
@update_time=Time.parse("1970-01-01")
|
15
33
|
@cache_timeout=DEF_CACHE_TIMEOUT
|
16
34
|
@cache_dir=DEF_DIR
|
35
|
+
@code=-1
|
17
36
|
Dir.mkdir DEF_DIR unless File.directory? DEF_DIR
|
18
37
|
self.update_method=(str)
|
19
38
|
end
|
20
39
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
40
|
+
# Force command execution. If another instance with
|
41
|
+
# the same command is in progress, no new execution
|
42
|
+
# will be started
|
25
43
|
def update
|
44
|
+
@content=''
|
26
45
|
File.open(@path, File::RDWR|File::CREAT, 0644) { |file|
|
27
46
|
if file.flock(File::LOCK_EX|File::LOCK_NB)
|
28
|
-
|
47
|
+
begin
|
48
|
+
IO.popen(@update_method){|pipe|
|
49
|
+
line=pipe.gets
|
50
|
+
while line
|
51
|
+
file.puts line
|
52
|
+
file.flush
|
53
|
+
@content = @content+line
|
54
|
+
line=pipe.gets
|
55
|
+
end
|
56
|
+
}
|
57
|
+
@code=$?.exitstatus
|
58
|
+
#warn "UPDATED: #{@content}/#{@code}"
|
59
|
+
rescue
|
60
|
+
@content=''
|
61
|
+
@code=-1
|
62
|
+
end
|
29
63
|
file.write @content
|
30
64
|
file.flush
|
65
|
+
File.open("#{@path}.code",File::RDWR|File::CREAT, 0644){|code_file|
|
66
|
+
code_file.puts @code
|
67
|
+
}
|
31
68
|
file.flock(File::LOCK_UN)
|
32
69
|
else
|
70
|
+
warn "CANNOT LOCK"
|
33
71
|
read_cache
|
34
72
|
end
|
35
73
|
@update_time=Time.now
|
@@ -38,6 +76,9 @@ class Exedb
|
|
38
76
|
@content
|
39
77
|
end
|
40
78
|
|
79
|
+
#
|
80
|
+
# Replace executing command
|
81
|
+
#
|
41
82
|
def update_method=(str)
|
42
83
|
@update_method=str
|
43
84
|
@key=generate_key str
|
@@ -45,38 +86,48 @@ class Exedb
|
|
45
86
|
# warn "key=#{@key}; path=#{@path}; u=#{str}"
|
46
87
|
end
|
47
88
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
@content=file.read
|
52
|
-
file.flock(File::LOCK_UN)
|
53
|
-
}
|
89
|
+
# Just alias for update_method=
|
90
|
+
def put(str)
|
91
|
+
self.update_method=(str)
|
54
92
|
end
|
55
93
|
|
94
|
+
#
|
95
|
+
# Get last execution result (stdout), or start new
|
96
|
+
# command execution and return result if cache is
|
97
|
+
# invalid.
|
98
|
+
#
|
56
99
|
def get
|
57
|
-
|
58
|
-
#warn "CACHED: #{state}"
|
59
|
-
case state
|
60
|
-
when :need_update
|
61
|
-
update
|
62
|
-
when :need_reread
|
63
|
-
#!!!warn "read cached"
|
64
|
-
read_cache
|
65
|
-
end
|
100
|
+
actualize
|
66
101
|
@content
|
67
102
|
end
|
68
103
|
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
#
|
104
|
+
#
|
105
|
+
# Get last execution return code.
|
106
|
+
# NOTE!!! It is also cached, even on error.
|
107
|
+
#
|
108
|
+
def code
|
109
|
+
actualize
|
110
|
+
@code
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Do not execute command - just peek in cache file...
|
115
|
+
# Usefull for intermediate command output peeking
|
116
|
+
#
|
117
|
+
def peek
|
118
|
+
begin
|
119
|
+
File.read(@path)
|
120
|
+
rescue
|
121
|
+
''
|
122
|
+
end
|
123
|
+
end
|
79
124
|
|
125
|
+
#
|
126
|
+
# Returns symbol of cache state:
|
127
|
+
# - updated = actual
|
128
|
+
# - need_update = new command execution needed
|
129
|
+
# - need_reread = just cache file reread is neede
|
130
|
+
#
|
80
131
|
def cache_state
|
81
132
|
if File.exists? @path
|
82
133
|
mtime=File.mtime(@path)
|
@@ -99,4 +150,32 @@ class Exedb
|
|
99
150
|
end
|
100
151
|
return false
|
101
152
|
end
|
153
|
+
|
154
|
+
protected
|
155
|
+
|
156
|
+
def actualize
|
157
|
+
case cache_state
|
158
|
+
when :need_update
|
159
|
+
update
|
160
|
+
when :need_reread
|
161
|
+
read_cache
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def generate_key u
|
166
|
+
return Digest::SHA256.hexdigest u
|
167
|
+
end
|
168
|
+
|
169
|
+
def read_cache
|
170
|
+
File.open(@path, File::RDONLY) { |file|
|
171
|
+
file.flock(File::LOCK_EX)
|
172
|
+
@content=file.read
|
173
|
+
File.open("#{@path}.code", File::RDONLY) { |code_file|
|
174
|
+
c=code_file.gets
|
175
|
+
c =~ /([0-9-]+)/
|
176
|
+
@code=$1.to_i
|
177
|
+
}
|
178
|
+
file.flock(File::LOCK_UN)
|
179
|
+
}
|
180
|
+
end
|
102
181
|
end
|
data/spec/exedb_spec.rb
CHANGED
@@ -73,4 +73,40 @@ describe Exedb do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
-
|
76
|
+
describe 'return code' do
|
77
|
+
it 'can be read' do
|
78
|
+
@db.code.must_be :==, 0
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'must be -1 if command cannnot be ran' do
|
82
|
+
@db=Exedb.new
|
83
|
+
@db.code.must_be :==, -1
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'must read cached value' do
|
87
|
+
@db=Exedb.new('x=`cat /tmp/mytestcode`; echo ">>$x<<"; exit $x')
|
88
|
+
@db2=Exedb.new('x=`cat /tmp/mytestcode`; echo ">>$x<<"; exit $x')
|
89
|
+
File.open("/tmp/mytestcode",'w'){|f| f.puts '1'}
|
90
|
+
@db.code
|
91
|
+
File.open("/tmp/mytestcode",'w'){|f| f.puts '2'}
|
92
|
+
@db2.update
|
93
|
+
|
94
|
+
@db.code.must_be :==, 2
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'intermediate output' do
|
99
|
+
it 'cam be read while command is in progress' do
|
100
|
+
CMD4='for i in 1 2 3 4; do echo x; sleep 1; done'
|
101
|
+
@db=Exedb.new(CMD4)
|
102
|
+
@db2=Exedb.new(CMD4)
|
103
|
+
t=Thread.new {
|
104
|
+
@db.get
|
105
|
+
}
|
106
|
+
sleep 3
|
107
|
+
x=@db2.peek
|
108
|
+
x.must_match /^x\nx(\nx?)$/m
|
109
|
+
t.join
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exedb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Zhumatiy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|