Class: Exedb

Inherits:
Object
  • Object
show all
Defined in:
lib/exedb.rb,
lib/exedb/version.rb

Overview

Database-like interface for long-running tasks.

Each instance can run single command (get). If two or more instances with the same command do ‘get’, then only first will really execute command, all others will wait for result (flock is used).

Results of command execution (stdout) is cached. Next ‘get’ will return cached results (unless cache timeout happened).

You can force execution, calling ‘update’ method.

Exit code is available via ‘code’ method

Constant Summary collapse

SLEEP_TIME =
1
DEF_DIR =
'/tmp/Exedb'
DEF_CACHE_TIMEOUT =
60
VERSION =
"0.2.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(str = '') ⇒ Exedb

Constructor



31
32
33
34
35
36
37
38
# File 'lib/exedb.rb', line 31

def initialize(str='')
  @update_time=Time.parse("1970-01-01")
  @cache_timeout=DEF_CACHE_TIMEOUT
  @cache_dir=DEF_DIR
  @code=-1
  Dir.mkdir DEF_DIR unless File.directory? DEF_DIR
  self.update_method=(str)
end

Instance Attribute Details

#cache_dirObject

Returns the value of attribute cache_dir.



25
26
27
# File 'lib/exedb.rb', line 25

def cache_dir
  @cache_dir
end

#cache_timeoutObject

Returns the value of attribute cache_timeout.



25
26
27
# File 'lib/exedb.rb', line 25

def cache_timeout
  @cache_timeout
end

#update_timeObject (readonly)

Returns the value of attribute update_time.



26
27
28
# File 'lib/exedb.rb', line 26

def update_time
  @update_time
end

Instance Method Details

#all_transform(&block) ⇒ Object

transform all command output at end of execution block is called with parameters: content, return code returned content replaces original output



109
110
111
112
113
114
115
116
117
# File 'lib/exedb.rb', line 109

def all_transform(&block)
  if block
    obj = Object.new
    obj.define_singleton_method(:_, &block)
    @alltransform=obj.method(:_).to_proc
  else
    @alltransform=nil
  end
end

#cache_stateObject

Returns symbol of cache state:

  • updated = actual

  • need_update = new command execution needed

  • need_reread = just cache file reread is neede



174
175
176
177
178
179
180
181
182
# File 'lib/exedb.rb', line 174

def cache_state
  if File.exists? @path
    mtime=File.mtime(@path)
    return :need_update if mtime+@cache_timeout<Time.now
    return :need_reread if @update_time<mtime
    return :updated
  end
  :need_update
end

#codeObject

Get last execution return code. NOTE!!! It is also cached, even on error.



151
152
153
154
# File 'lib/exedb.rb', line 151

def code
  actualize
  @code
end

#getObject

Get last execution result (stdout), or start new command execution and return result if cache is invalid.



142
143
144
145
# File 'lib/exedb.rb', line 142

def get
  actualize
  @content
end

#line_transform(&block) ⇒ Object

transform each line in command output if nil is returned, line is skipped



87
88
89
90
91
92
93
94
95
# File 'lib/exedb.rb', line 87

def line_transform(&block)
  if block
    obj = Object.new
    obj.define_singleton_method(:_, &block)
    @transform=obj.method(:_).to_proc
  else
    @transform=nil
  end
end

#no_all_transformObject



119
120
121
# File 'lib/exedb.rb', line 119

def no_all_transform
  @alltransform=nil
end

#no_line_transformObject

cancel transformation each line



100
101
102
# File 'lib/exedb.rb', line 100

def no_line_transform
  @transform=nil    
end

#peekObject

Do not execute command - just peek in cache file… Usefull for intermediate command output peeking



160
161
162
163
164
165
166
# File 'lib/exedb.rb', line 160

def peek
  begin
    File.read(@path)      
  rescue
    ''
  end
end

#put(str) ⇒ Object

Just alias for update_method=



133
134
135
# File 'lib/exedb.rb', line 133

def put(str)
  self.update_method=(str)
end

#updateObject

Force command execution. If another instance with the same command is in progress, no new execution will be started



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/exedb.rb', line 43

def update
  @content=''
  File.open(@path, File::RDWR|File::CREAT, 0644) { |file|
    if file.flock(File::LOCK_EX|File::LOCK_NB)
      begin
        IO.popen(@update_method){|pipe|
          line=pipe.gets
          while line
            line=@transform.call(line) if @transform
            if line
              file.puts line
              file.flush
              @content = @content+line
            end
            line=pipe.gets
          end
        }
        @code=$?.exitstatus
        #warn "UPDATED: #{@content}/#{@code}"
      rescue
        @content=''
        @code=-1
      end
      @content=@alltransform.call(@content,@code) if @alltransform
      file.write @content
      file.flush
      File.open("#{@path}.code",File::RDWR|File::CREAT, 0644){|code_file|
        code_file.puts @code
      }
      file.flock(File::LOCK_UN)
    else
      warn "CANNOT LOCK"
      read_cache
    end
    @update_time=Time.now
  }
  #!!!warn "UPDATED!'"
  @content
end

#update_in_progress?Boolean

Returns:

  • (Boolean)


184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/exedb.rb', line 184

def update_in_progress?
  if File.exists? @path
    File.open(@path, File::RDONLY) { |file|
      if file.flock(File::LOCK_EX|File::LOCK_NB)
        file.flock(File::LOCK_UN)
        return false
      end
    }
    return true
  end
  return false
end

#update_method=(str) ⇒ Object

Replace executing command



125
126
127
128
129
130
# File 'lib/exedb.rb', line 125

def update_method=(str)
  @update_method=str
  @key=generate_key str
  @path=File.join(DEF_DIR, @key)
#    warn "key=#{@key}; path=#{@path}; u=#{str}"
end