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 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