exedb 0.0.3 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|