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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5372419cdccd2512e7cce207d8a2f5b776154827
4
- data.tar.gz: 6666d7b9cb0c9024fd98bf705b574a9057e3c262
3
+ metadata.gz: 2edd3f5d079de4f4fe759bc639c12848fdc1b384
4
+ data.tar.gz: ea2957752bc6856ed29bc50a1813caa977a46bf4
5
5
  SHA512:
6
- metadata.gz: 926ad8b21503f804fa0103ae086cbf0f462cc042bac75d2de27085ced49b6d7a967436bb5ce030dce57e2c681d07ca056da116c66786ce61c168f4d014a9c33a
7
- data.tar.gz: aed6a928cb676ad836e8075f288480aa1b887983d882e35ca7391026a6efccb07da1cefc610642ca05170cf9278f8a7964c55cf5637eab43cea0a64e3883b8d2
6
+ metadata.gz: fb50137af58069d48b51c058f876e268ba46913ce5c0ce1b57a39ad2892ae3919775ee21f42ad9858df3177406ffa098e8e97bc41e45db882b1273866ed39b90
7
+ data.tar.gz: d1dcc865f0751ed9115334b9cd6751c532a63f4c839c6b47d9747e0c5a58a93da4f1c6c2b273fb9d7a5f84eb0c5f86d1c06f62f5e80c0a9cbf83c61812123c54
data/lib/exedb/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Exedb
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.1"
3
3
  end
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
- def generate_key u
22
- return Digest::SHA256.hexdigest u
23
- end
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
- @content=`#{@update_method}`
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
- def read_cache
49
- File.open(@path, File::RDONLY) { |file|
50
- file.flock(File::LOCK_EX)
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
- state=cache_state
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
- # def get
70
- # return get_cached
71
- # #warn "Get: #{@update_time}+#{@cache_timeout}>#{Time.now}"
72
- # if @update_time+@cache_timeout>Time.now
73
- # # not need to update cache
74
- # get_cached
75
- # else
76
- # update
77
- # end
78
- # end
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
- end
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.0.3
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-01-31 00:00:00.000000000 Z
11
+ date: 2014-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler