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.2"

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



117
118
119
120
121
122
123
124
125
# File 'lib/exedb.rb', line 117

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



182
183
184
185
186
187
188
189
190
# File 'lib/exedb.rb', line 182

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.



159
160
161
162
# File 'lib/exedb.rb', line 159

def code
  actualize
  @code
end

#getObject

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



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

def get
  actualize
  @content
end

#line_transform(&block) ⇒ Object

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



95
96
97
98
99
100
101
102
103
# File 'lib/exedb.rb', line 95

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



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

def no_all_transform
  @alltransform=nil
end

#no_line_transformObject

cancel transformation each line



108
109
110
# File 'lib/exedb.rb', line 108

def no_line_transform
  @transform=nil    
end

#peekObject

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



168
169
170
171
172
173
174
# File 'lib/exedb.rb', line 168

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

#put(str) ⇒ Object

Just alias for update_method=



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

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
82
83
84
85
86
87
88
89
# File 'lib/exedb.rb', line 43

def update
  @content=''

  # create file if needed
  unless File.file?(@path)
    File.open(@path,File::RDWR|File::CREAT,0644){|f|}
  end

  File.open(@path, "r+:UTF-8") { |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
      rescue
        @content=''
        @code=-1
      end
      if @alltransform
        @content=@alltransform.call(@content,@code)
        file.seek(0,IO::SEEK_SET)
        file.write @content
        file.truncate(@content.size)
        file.flush
      end
      File.open("#{@path}.code",File::RDWR|File::CREAT, 0644){|code_file|
        code_file.puts @code
      }
      file.flock(File::LOCK_UN)
    else
      read_cache
    end
    @update_time=Time.now
  }
  #!!!warn "UPDATED!'"
  @content
end

#update_in_progress?Boolean

Returns:

  • (Boolean)


192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/exedb.rb', line 192

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



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

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