updater 0.3.2 → 0.9.0
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.
- data/VERSION +1 -1
 - data/lib/updater/fork_worker.rb +24 -12
 - data/lib/updater/orm/datamapper.rb +36 -9
 - data/lib/updater/orm/orm.rb +16 -0
 - data/lib/updater/setup.rb +72 -15
 - data/lib/updater/update.rb +41 -6
 - data/spec/named_request_spec.rb +25 -5
 - metadata +2 -2
 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.9.0
         
     | 
    
        data/lib/updater/fork_worker.rb
    CHANGED
    
    | 
         @@ -35,7 +35,7 @@ module Updater 
     | 
|
| 
       35 
35 
     | 
    
         
             
                    logger.info "Max Workers set to #{@max_workers}"
         
     | 
| 
       36 
36 
     | 
    
         
             
                    @timeout = options[:timeout] || 60
         
     | 
| 
       37 
37 
     | 
    
         
             
                    logger.info "Timeout set to #{@timeout} sec."
         
     | 
| 
       38 
     | 
    
         
            -
                    @current_workers = 1
         
     | 
| 
      
 38 
     | 
    
         
            +
                    @current_workers = 1 #we will actually add this worker the first time through the master loop
         
     | 
| 
       39 
39 
     | 
    
         
             
                    @workers = {} #key is pid value is worker class
         
     | 
| 
       40 
40 
     | 
    
         
             
                    @uptime = Time.now
         
     | 
| 
       41 
41 
     | 
    
         
             
                    @downtime = Time.now
         
     | 
| 
         @@ -92,10 +92,9 @@ module Updater 
     | 
|
| 
       92 
92 
     | 
    
         
             
                  # * :timeout : how long can a worker be inactive before being killed
         
     | 
| 
       93 
93 
     | 
    
         
             
                  # * :sockets: 0 or more IO objects that should wake up master to alert it that new data is availible
         
     | 
| 
       94 
94 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
                  def start( 
     | 
| 
      
 95 
     | 
    
         
            +
                  def start(options = {})
         
     | 
| 
       96 
96 
     | 
    
         
             
                    initial_setup(options) #need this for logger
         
     | 
| 
       97 
97 
     | 
    
         
             
                    logger.info "*** Starting Master Process***"
         
     | 
| 
       98 
     | 
    
         
            -
                    @stream = stream
         
     | 
| 
       99 
98 
     | 
    
         
             
                    logger.info "* Adding the first round of workers *"
         
     | 
| 
       100 
99 
     | 
    
         
             
                    maintain_worker_count
         
     | 
| 
       101 
100 
     | 
    
         
             
                    QUEUE_SIGS.each { |sig| trap_deferred(sig) }
         
     | 
| 
         @@ -121,13 +120,13 @@ module Updater 
     | 
|
| 
       121 
120 
     | 
    
         
             
                      logger.fatal "10 consecutive errors! Abandoning Master process"
         
     | 
| 
       122 
121 
     | 
    
         
             
                    end
         
     | 
| 
       123 
122 
     | 
    
         
             
                    stop # gracefully shutdown all workers on our way out
         
     | 
| 
       124 
     | 
    
         
            -
                    logger. 
     | 
| 
      
 123 
     | 
    
         
            +
                    logger.warn "-=-=-=- master process Exiting -=-=-=-\n\n"
         
     | 
| 
       125 
124 
     | 
    
         
             
                  end
         
     | 
| 
       126 
125 
     | 
    
         | 
| 
       127 
126 
     | 
    
         
             
                  def stop(graceful = true)
         
     | 
| 
       128 
127 
     | 
    
         
             
                    trap(:USR2,"IGNORE")
         
     | 
| 
       129 
128 
     | 
    
         
             
                    [:INT,:TERM].each {|signal| trap(signal,"DEFAULT") }
         
     | 
| 
       130 
     | 
    
         
            -
                    puts "Quitting. I need 30 seconds to stop my workers..."
         
     | 
| 
      
 129 
     | 
    
         
            +
                    puts "Quitting. I need 30 seconds to stop my workers..." unless @workers.empty?
         
     | 
| 
       131 
130 
     | 
    
         
             
                    limit = Time.now + 30
         
     | 
| 
       132 
131 
     | 
    
         
             
                    signal_each_worker(graceful ? :QUIT : :TERM)
         
     | 
| 
       133 
132 
     | 
    
         
             
                    until @workers.empty? || Time.now > limit
         
     | 
| 
         @@ -140,15 +139,26 @@ module Updater 
     | 
|
| 
       140 
139 
     | 
    
         
             
                  def master_sleep
         
     | 
| 
       141 
140 
     | 
    
         
             
                    begin
         
     | 
| 
       142 
141 
     | 
    
         
             
                      timeout = calc_timeout
         
     | 
| 
       143 
     | 
    
         
            -
                      logger.debug { "Sleeping for #{timeout}" } 
     | 
| 
      
 142 
     | 
    
         
            +
                      logger.debug { "Sleeping for #{timeout}" }
         
     | 
| 
       144 
143 
     | 
    
         
             
                      ready, _1, _2 = IO.select(@wakeup_set, nil, nil, timeout)
         
     | 
| 
       145 
     | 
    
         
            -
                      return unless ready && ready.first #just wakeup and run maintance
         
     | 
| 
       146 
     | 
    
         
            -
                       
     | 
| 
      
 144 
     | 
    
         
            +
                      return unless ready && ready.first #timeout hit,  just wakeup and run maintance
         
     | 
| 
      
 145 
     | 
    
         
            +
                      add_connection(ready.first) and return if ready.first.respond_to?(:accept) #open a new incomming connection 
         
     | 
| 
      
 146 
     | 
    
         
            +
                      @signal_queue << :DATA unless ready.first == @self_pipe.first
         
     | 
| 
       147 
147 
     | 
    
         
             
                      loop {ready.first.read_nonblock(16 * 1024)}
         
     | 
| 
      
 148 
     | 
    
         
            +
                    rescue EOFError #somebody closed thier connection
         
     | 
| 
      
 149 
     | 
    
         
            +
                      logger.info "closed socket connection"
         
     | 
| 
      
 150 
     | 
    
         
            +
                      @wakeup_set.delete ready.first
         
     | 
| 
      
 151 
     | 
    
         
            +
                      ready.first.close
         
     | 
| 
       148 
152 
     | 
    
         
             
                    rescue Errno::EAGAIN, Errno::EINTR
         
     | 
| 
       149 
153 
     | 
    
         
             
                    end
         
     | 
| 
       150 
154 
     | 
    
         
             
                  end
         
     | 
| 
       151 
155 
     | 
    
         | 
| 
      
 156 
     | 
    
         
            +
                  def add_connection(server)
         
     | 
| 
      
 157 
     | 
    
         
            +
                    @wakeup_set << server.accept_nonblock
         
     | 
| 
      
 158 
     | 
    
         
            +
                    logger.info "opened socket connection: [#{@wakeup_set.last.addr.join(', ')}]"
         
     | 
| 
      
 159 
     | 
    
         
            +
                  rescue Errno::EAGAIN, Errno::EINTR
         
     | 
| 
      
 160 
     | 
    
         
            +
                  end
         
     | 
| 
      
 161 
     | 
    
         
            +
                  
         
     | 
| 
       152 
162 
     | 
    
         
             
                  def calc_timeout
         
     | 
| 
       153 
163 
     | 
    
         
             
                    Time.now - [@uptime, @downtime].max < @timeout ? @timeout / 8 : 2*@timeout
         
     | 
| 
       154 
164 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -219,6 +229,7 @@ module Updater 
     | 
|
| 
       219 
229 
     | 
    
         | 
| 
       220 
230 
     | 
    
         
             
                  def add_worker(worker_number)
         
     | 
| 
       221 
231 
     | 
    
         
             
                    worker = WorkerMonitor.new(worker_number,Updater::Util.tempio)
         
     | 
| 
      
 232 
     | 
    
         
            +
                    Update.orm.before_fork
         
     | 
| 
       222 
233 
     | 
    
         
             
                    pid = Process.fork do
         
     | 
| 
       223 
234 
     | 
    
         
             
                      fork_cleanup
         
     | 
| 
       224 
235 
     | 
    
         
             
                      self.new(@pipe,worker).run
         
     | 
| 
         @@ -229,6 +240,7 @@ module Updater 
     | 
|
| 
       229 
240 
     | 
    
         | 
| 
       230 
241 
     | 
    
         
             
                  def fork_cleanup
         
     | 
| 
       231 
242 
     | 
    
         
             
                    QUEUE_SIGS.each { |signal| trap(signal,"IGNORE") }
         
     | 
| 
      
 243 
     | 
    
         
            +
                    Update.orm.after_fork
         
     | 
| 
       232 
244 
     | 
    
         
             
                    if @self_pipe !=nil
         
     | 
| 
       233 
245 
     | 
    
         
             
                      @self_pipe.each {|io| io.close}
         
     | 
| 
       234 
246 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -327,8 +339,8 @@ module Updater 
     | 
|
| 
       327 
339 
     | 
    
         
             
                      wait_for(delay) if @continue
         
     | 
| 
       328 
340 
     | 
    
         
             
                    rescue Exception=> e
         
     | 
| 
       329 
341 
     | 
    
         
             
                      say "Caught exception in Job Loop"
         
     | 
| 
       330 
     | 
    
         
            -
                      say e. 
     | 
| 
       331 
     | 
    
         
            -
                      say "||=========\n|| Backtrace\n|| " + e.backtrace.join("\n|| ") + "\n||========="
         
     | 
| 
      
 342 
     | 
    
         
            +
                      say e.inspect
         
     | 
| 
      
 343 
     | 
    
         
            +
                      say "\n||=========\n|| Backtrace\n|| " + e.backtrace.join("\n|| ") + "\n||========="
         
     | 
| 
       332 
344 
     | 
    
         
             
                      Update.clear_locks(self)
         
     | 
| 
       333 
345 
     | 
    
         
             
                      exit; #die and be replaced by the master process
         
     | 
| 
       334 
346 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -392,8 +404,8 @@ module Updater 
     | 
|
| 
       392 
404 
     | 
    
         
             
                  #need to wait for another job
         
     | 
| 
       393 
405 
     | 
    
         
             
                  t = Time.now + delay
         
     | 
| 
       394 
406 
     | 
    
         
             
                  while Time.now < t && @continue
         
     | 
| 
       395 
     | 
    
         
            -
                    delay = [@timeout,t-Time.now].min
         
     | 
| 
       396 
     | 
    
         
            -
                    debug "No Jobs; #{name} sleeping for #{delay}:  [#{@timeout},#{t - Time.now}].min"
         
     | 
| 
      
 407 
     | 
    
         
            +
                    delay = [@timeout/2,t-Time.now].min
         
     | 
| 
      
 408 
     | 
    
         
            +
                    debug "No Jobs; #{name} sleeping for #{delay}:  [#{@timeout/2},#{t - Time.now}].min"
         
     | 
| 
       397 
409 
     | 
    
         
             
                    wakeup,_1,_2 = select([@stream],nil,nil,delay)
         
     | 
| 
       398 
410 
     | 
    
         
             
                    heartbeat
         
     | 
| 
       399 
411 
     | 
    
         
             
                    if wakeup
         
     | 
| 
         @@ -19,13 +19,13 @@ module Updater 
     | 
|
| 
       19 
19 
     | 
    
         
             
                  storage_names[:default] = "updates"
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
                  property :id, Serial
         
     | 
| 
       22 
     | 
    
         
            -
                  property :time, Integer
         
     | 
| 
       23 
     | 
    
         
            -
                  property :target, Class
         
     | 
| 
       24 
     | 
    
         
            -
                  property :finder, String
         
     | 
| 
       25 
     | 
    
         
            -
                  property :finder_args, Yaml
         
     | 
| 
      
 22 
     | 
    
         
            +
                  property :time, Integer, :index=>true
         
     | 
| 
      
 23 
     | 
    
         
            +
                  property :target, Class, :index=>:for_target
         
     | 
| 
      
 24 
     | 
    
         
            +
                  property :finder, String, :index=>:for_target
         
     | 
| 
      
 25 
     | 
    
         
            +
                  property :finder_args, Yaml, :index=>:for_target
         
     | 
| 
       26 
26 
     | 
    
         
             
                  property :method, String
         
     | 
| 
       27 
27 
     | 
    
         
             
                  property :method_args, Object, :lazy=>false
         
     | 
| 
       28 
     | 
    
         
            -
                  property :name, String, :length=>255
         
     | 
| 
      
 28 
     | 
    
         
            +
                  property :name, String, :length=>255, :index=>true
         
     | 
| 
       29 
29 
     | 
    
         
             
                  property :lock_name, String
         
     | 
| 
       30 
30 
     | 
    
         
             
                  property :persistant, Boolean
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
         @@ -112,6 +112,7 @@ module Updater 
     | 
|
| 
       112 
112 
     | 
    
         
             
                      return nxt.time - tnow
         
     | 
| 
       113 
113 
     | 
    
         
             
                    end
         
     | 
| 
       114 
114 
     | 
    
         | 
| 
      
 115 
     | 
    
         
            +
                    #Returns the Locked Job or nil if no jobs were availible.
         
     | 
| 
       115 
116 
     | 
    
         
             
                    def lock_next(worker)
         
     | 
| 
       116 
117 
     | 
    
         
             
                      updates = worker_set
         
     | 
| 
       117 
118 
     | 
    
         
             
                      unless updates.empty?
         
     | 
| 
         @@ -124,6 +125,7 @@ module Updater 
     | 
|
| 
       124 
125 
     | 
    
         
             
                        updates.each do |u|
         
     | 
| 
       125 
126 
     | 
    
         
             
                          return u if u.lock(worker)
         
     | 
| 
       126 
127 
     | 
    
         
             
                        end
         
     | 
| 
      
 128 
     | 
    
         
            +
                        return nil
         
     | 
| 
       127 
129 
     | 
    
         
             
                      end
         
     | 
| 
       128 
130 
     | 
    
         
             
                    rescue DataObjects::ConnectionError
         
     | 
| 
       129 
131 
     | 
    
         
             
                      sleep 0.1
         
     | 
| 
         @@ -140,7 +142,32 @@ module Updater 
     | 
|
| 
       140 
142 
     | 
    
         
             
                    end
         
     | 
| 
       141 
143 
     | 
    
         | 
| 
       142 
144 
     | 
    
         
             
                    def for(mytarget, myfinder, myfinder_args, myname=nil)
         
     | 
| 
       143 
     | 
    
         
            -
                       
     | 
| 
      
 145 
     | 
    
         
            +
                      search = all(
         
     | 
| 
      
 146 
     | 
    
         
            +
                          :target=>mytarget,
         
     | 
| 
      
 147 
     | 
    
         
            +
                          :finder=>myfinder,
         
     | 
| 
      
 148 
     | 
    
         
            +
                          :finder_args=>myfinder_args, 
         
     | 
| 
      
 149 
     | 
    
         
            +
                          :lock_name=>nil
         
     | 
| 
      
 150 
     | 
    
         
            +
                        )
         
     | 
| 
      
 151 
     | 
    
         
            +
                      myname ? search.all(:name=>myname ) : search
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
                    
         
     | 
| 
      
 154 
     | 
    
         
            +
                    #For the server only, setup the connection to the database
         
     | 
| 
      
 155 
     | 
    
         
            +
                    def setup(options)
         
     | 
| 
      
 156 
     | 
    
         
            +
                      ::DataMapper.logger = options.delete(:logger)
         
     | 
| 
      
 157 
     | 
    
         
            +
                      ::DataMapper.setup(:default,options)
         
     | 
| 
      
 158 
     | 
    
         
            +
                    end
         
     | 
| 
      
 159 
     | 
    
         
            +
                    
         
     | 
| 
      
 160 
     | 
    
         
            +
                    # For pooled connections it is necessary to empty the pool of the parents connections so that they
         
     | 
| 
      
 161 
     | 
    
         
            +
                    # do not comtiminate the child pool. Note that while Datamapper is thread safe, it is not safe accross a process fork.
         
     | 
| 
      
 162 
     | 
    
         
            +
                    def before_fork
         
     | 
| 
      
 163 
     | 
    
         
            +
                      return unless (defined? ::DataObjects::Pooling)
         
     | 
| 
      
 164 
     | 
    
         
            +
                      return if ::DataMapper.repository.adapter.kind_of?(::DataMapper::Adapters::Sqlite3Adapter)
         
     | 
| 
      
 165 
     | 
    
         
            +
                      ::DataMapper.logger.debug "+-+-+-+-+ Cleaning up connection pool (#{::DataObjects::Pooling.pools.length}) +-+-+-+-+"
         
     | 
| 
      
 166 
     | 
    
         
            +
                      ::DataObjects::Pooling.pools.each {|p| p.dispose} 
         
     | 
| 
      
 167 
     | 
    
         
            +
                    end
         
     | 
| 
      
 168 
     | 
    
         
            +
                    
         
     | 
| 
      
 169 
     | 
    
         
            +
                    def after_fork
         
     | 
| 
      
 170 
     | 
    
         
            +
                      
         
     | 
| 
       144 
171 
     | 
    
         
             
                    end
         
     | 
| 
       145 
172 
     | 
    
         | 
| 
       146 
173 
     | 
    
         
             
                  private
         
     | 
| 
         @@ -152,7 +179,7 @@ module Updater 
     | 
|
| 
       152 
179 
     | 
    
         
             
                      options = {:lock_name=>nil,:limit=>limit, :order=>[:time.asc]}.merge(options)
         
     | 
| 
       153 
180 
     | 
    
         
             
                      current.all(options)
         
     | 
| 
       154 
181 
     | 
    
         
             
                    end
         
     | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
       156 
183 
     | 
    
         
             
                    def lock
         
     | 
| 
       157 
184 
     | 
    
         | 
| 
       158 
185 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -168,8 +195,8 @@ module Updater 
     | 
|
| 
       168 
195 
     | 
    
         
             
                  belongs_to :caller, :model=>Updater::ORM::DataMapper, :child_key=>[:caller_id]
         
     | 
| 
       169 
196 
     | 
    
         
             
                  belongs_to :target, :model=>Updater::ORM::DataMapper, :child_key=>[:target_id]
         
     | 
| 
       170 
197 
     | 
    
         | 
| 
       171 
     | 
    
         
            -
                  property :params, Object, : 
     | 
| 
       172 
     | 
    
         
            -
                  property :occasion, String,  : 
     | 
| 
      
 198 
     | 
    
         
            +
                  property :params, Object, :required=>false 
         
     | 
| 
      
 199 
     | 
    
         
            +
                  property :occasion, String,  :required=>true
         
     | 
| 
       173 
200 
     | 
    
         
             
                end
         
     | 
| 
       174 
201 
     | 
    
         | 
| 
       175 
202 
     | 
    
         
             
              end#ORM
         
     | 
    
        data/lib/updater/orm/orm.rb
    CHANGED
    
    | 
         @@ -217,6 +217,22 @@ module Updater 
     | 
|
| 
       217 
217 
     | 
    
         
             
                    NotImplementedError
         
     | 
| 
       218 
218 
     | 
    
         
             
                  end
         
     | 
| 
       219 
219 
     | 
    
         | 
| 
      
 220 
     | 
    
         
            +
                  # This method is the generic way to setup the datastore.  Options is a hash one of whose fields
         
     | 
| 
      
 221 
     | 
    
         
            +
                  # will be :logger, the logger instance to pass on to the ORM.  The rest of the options are ORM 
         
     | 
| 
      
 222 
     | 
    
         
            +
                  # spesific.  The function should prepair a connection to the datastore using the given options.
         
     | 
| 
      
 223 
     | 
    
         
            +
                  # If the connection cannot be prepaired then an appropriate error should be raised.
         
     | 
| 
      
 224 
     | 
    
         
            +
                  def setup(options)
         
     | 
| 
      
 225 
     | 
    
         
            +
                    NotImplementedError 
         
     | 
| 
      
 226 
     | 
    
         
            +
                  end
         
     | 
| 
      
 227 
     | 
    
         
            +
                  
         
     | 
| 
      
 228 
     | 
    
         
            +
                  # This method is called by the child before a fork call.  It allows the ORM to clean up any connections
         
     | 
| 
      
 229 
     | 
    
         
            +
                  # Made by the parent and establish new connections if necessary.
         
     | 
| 
      
 230 
     | 
    
         
            +
                  def before_fork
         
     | 
| 
      
 231 
     | 
    
         
            +
                    
         
     | 
| 
      
 232 
     | 
    
         
            +
                  end
         
     | 
| 
      
 233 
     | 
    
         
            +
                  
         
     | 
| 
      
 234 
     | 
    
         
            +
                  def after_fork
         
     | 
| 
      
 235 
     | 
    
         
            +
                  
         
     | 
| 
       220 
236 
     | 
    
         
             
                  # Optional, but strongly recomended.
         
     | 
| 
       221 
237 
     | 
    
         
             
                  #
         
     | 
| 
       222 
238 
     | 
    
         
             
                  # For any datastore that permits, return and Array of all delayed, chained, and current but not locked jobs that reference 
         
     | 
    
        data/lib/updater/setup.rb
    CHANGED
    
    | 
         @@ -14,6 +14,10 @@ module Updater 
     | 
|
| 
       14 
14 
     | 
    
         
             
                    new(config_file).stop
         
     | 
| 
       15 
15 
     | 
    
         
             
                  end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
      
 17 
     | 
    
         
            +
                  def client_setup(options = {})
         
     | 
| 
      
 18 
     | 
    
         
            +
                    new(config_file, options).client_setup
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  
         
     | 
| 
       17 
21 
     | 
    
         
             
                  def monitor
         
     | 
| 
       18 
22 
     | 
    
         | 
| 
       19 
23 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -27,44 +31,84 @@ module Updater 
     | 
|
| 
       27 
31 
     | 
    
         
             
                  end
         
     | 
| 
       28 
32 
     | 
    
         
             
                end
         
     | 
| 
       29 
33 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                ROOT = File.dirname(self.config_file)
         
     | 
| 
      
 34 
     | 
    
         
            +
                ROOT = File.dirname(self.config_file || Dir.pwd)
         
     | 
| 
       31 
35 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                 
     | 
| 
      
 36 
     | 
    
         
            +
                #extended used for clients who wnat to override parameters
         
     | 
| 
      
 37 
     | 
    
         
            +
                def initialize(file_or_hash, extended = {})
         
     | 
| 
       33 
38 
     | 
    
         
             
                  @options = file_or_hash.kind_of?(Hash) ? file_or_hash : load_file(file_or_hash)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @options.merge(extended)
         
     | 
| 
       34 
40 
     | 
    
         
             
                  @options[:pid_file] ||= File.join(ROOT,'updater.pid')
         
     | 
| 
       35 
41 
     | 
    
         
             
                  @options[:host] ||= "localhost"
         
     | 
| 
       36 
     | 
    
         
            -
                  @logger = Logger.new(@options[:log_file] || STDOUT)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @logger = @options[:logger] || Logger.new(@options[:log_file] || STDOUT)
         
     | 
| 
       37 
43 
     | 
    
         
             
                  level = Logger::SEV_LABEL.index(@options[:log_level].upcase) if @options[:log_level]
         
     | 
| 
       38 
44 
     | 
    
         
             
                  @logger.level = level || Logger::WARN 
         
     | 
| 
       39 
45 
     | 
    
         
             
                end
         
     | 
| 
       40 
46 
     | 
    
         | 
| 
       41 
47 
     | 
    
         
             
                def start
         
     | 
| 
       42 
     | 
    
         
            -
                  @logger.warn "Starting Loop"
         
     | 
| 
       43 
48 
     | 
    
         
             
                  pid = Process.fork do
         
     | 
| 
       44 
49 
     | 
    
         
             
                    _start
         
     | 
| 
       45 
50 
     | 
    
         
             
                  end
         
     | 
| 
       46 
     | 
    
         
            -
                  @logger.warn " 
     | 
| 
      
 51 
     | 
    
         
            +
                  @logger.warn "Successfully started Master Loop at pid #{pid}"
         
     | 
| 
      
 52 
     | 
    
         
            +
                  puts "Job Queue Processor Started at PID: #{pid}"
         
     | 
| 
       47 
53 
     | 
    
         
             
                end
         
     | 
| 
       48 
54 
     | 
    
         | 
| 
       49 
55 
     | 
    
         
             
                def stop
         
     | 
| 
       50 
56 
     | 
    
         
             
                  Process.kill("TERM",File.read(@options[:pid_file]).to_i)
         
     | 
| 
       51 
57 
     | 
    
         
             
                end
         
     | 
| 
       52 
58 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                 
     | 
| 
      
 59 
     | 
    
         
            +
                # The client is responcible for loading classes and making connections.  We will simply setup the Updater spesifics
         
     | 
| 
      
 60 
     | 
    
         
            +
                def client_setup
         
     | 
| 
      
 61 
     | 
    
         
            +
                  set_orm
         
     | 
| 
      
 62 
     | 
    
         
            +
                  
         
     | 
| 
      
 63 
     | 
    
         
            +
                  if @options[:socket] && File.exists?(@options[:socket])
         
     | 
| 
      
 64 
     | 
    
         
            +
                    Updater::Update.socket = UNIXSocket.new(@options[:socket])
         
     | 
| 
      
 65 
     | 
    
         
            +
                  elsif @options[:udp]
         
     | 
| 
      
 66 
     | 
    
         
            +
                    socket = UDPSocket.new()
         
     | 
| 
      
 67 
     | 
    
         
            +
                    socket.connect(@options[:host],@options[:udp])
         
     | 
| 
      
 68 
     | 
    
         
            +
                    Updater::Update.socket = socket
         
     | 
| 
      
 69 
     | 
    
         
            +
                  elsif @options[:tcp]
         
     | 
| 
      
 70 
     | 
    
         
            +
                    Updater::Update.socket = TCPSocket.new(@options[:host],@options[:tcp])
         
     | 
| 
      
 71 
     | 
    
         
            +
                  elsif @options[:remote]
         
     | 
| 
      
 72 
     | 
    
         
            +
                    raise NotImplimentedError #For future Authenticated Http Rest Server
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
                  
         
     | 
| 
      
 75 
     | 
    
         
            +
                  #set PID
         
     | 
| 
      
 76 
     | 
    
         
            +
                  if File.exists? @options[:pid_file]
         
     | 
| 
      
 77 
     | 
    
         
            +
                    Updater::Update.pid = File.read(@options[:pid_file]).strip
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  
         
     | 
| 
       54 
80 
     | 
    
         | 
| 
       55 
81 
     | 
    
         
             
                end
         
     | 
| 
       56 
82 
     | 
    
         | 
| 
       57 
83 
     | 
    
         
             
                private
         
     | 
| 
       58 
84 
     | 
    
         | 
| 
      
 85 
     | 
    
         
            +
                def set_orm
         
     | 
| 
      
 86 
     | 
    
         
            +
                  #don't setup twice.  Client setup might call this as part of server setup in which case it is already done
         
     | 
| 
      
 87 
     | 
    
         
            +
                  return false if Updater::Update.orm
         
     | 
| 
      
 88 
     | 
    
         
            +
                  orm = @options[:orm] || "datamapper"
         
     | 
| 
      
 89 
     | 
    
         
            +
                  case orm.downcase
         
     | 
| 
      
 90 
     | 
    
         
            +
                    when "datamapper"
         
     | 
| 
      
 91 
     | 
    
         
            +
                      require 'updater/orm/datamapper'
         
     | 
| 
      
 92 
     | 
    
         
            +
                      Updater::Update.orm = ORM::DataMapper
         
     | 
| 
      
 93 
     | 
    
         
            +
                    when "mongodb"
         
     | 
| 
      
 94 
     | 
    
         
            +
                      require 'updater/orm/mongodb'
         
     | 
| 
      
 95 
     | 
    
         
            +
                      Updater::Update.orm = ORM::MongoDB
         
     | 
| 
      
 96 
     | 
    
         
            +
                    when "activerecord"
         
     | 
| 
      
 97 
     | 
    
         
            +
                      require 'updater/orm/activerecord'
         
     | 
| 
      
 98 
     | 
    
         
            +
                      Updater::Update.orm = ORM::ActiveRecord
         
     | 
| 
      
 99 
     | 
    
         
            +
                    else
         
     | 
| 
      
 100 
     | 
    
         
            +
                      require "update/orm/#{orm}"
         
     | 
| 
      
 101 
     | 
    
         
            +
                      Updater::Update.orm = Object.const_get("ORM").const_get(orm.capitalize)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
                  @logger.info "Data store '#{orm}' selected"
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
                
         
     | 
| 
       59 
106 
     | 
    
         
             
                def _start
         
     | 
| 
       60 
107 
     | 
    
         
             
                  #set ORM
         
     | 
| 
       61 
     | 
    
         
            -
                   
     | 
| 
       62 
     | 
    
         
            -
                  Updater::Update.orm = ORM::DataMapper
         
     | 
| 
       63 
     | 
    
         
            -
                  
         
     | 
| 
      
 108 
     | 
    
         
            +
                  set_orm
         
     | 
| 
       64 
109 
     | 
    
         
             
                  #init DataStore
         
     | 
| 
       65 
     | 
    
         
            -
                   
     | 
| 
       66 
     | 
    
         
            -
                   
     | 
| 
       67 
     | 
    
         
            -
                  
         
     | 
| 
      
 110 
     | 
    
         
            +
                  default_options = {:adapter=>'sqlite3', :database=>'./default.db'}
         
     | 
| 
      
 111 
     | 
    
         
            +
                  Updater::Update.orm.setup((@options[:database] || @options[:orm_setup] || default_options).merge(:logger=>@logger))
         
     | 
| 
       68 
112 
     | 
    
         
             
                  #load Models
         
     | 
| 
       69 
113 
     | 
    
         | 
| 
       70 
114 
     | 
    
         
             
                  models = @options[:models] || Dir.glob('./app/models/**/*.rb')
         
     | 
| 
         @@ -73,11 +117,13 @@ module Updater 
     | 
|
| 
       73 
117 
     | 
    
         
             
                  end
         
     | 
| 
       74 
118 
     | 
    
         | 
| 
       75 
119 
     | 
    
         
             
                  #establish Connections
         
     | 
| 
      
 120 
     | 
    
         
            +
                  @options[:host] ||= 'localhost'
         
     | 
| 
       76 
121 
     | 
    
         
             
                  #Unix Socket -- name at @options[:socket]
         
     | 
| 
       77 
122 
     | 
    
         
             
                  if @options[:socket]
         
     | 
| 
       78 
123 
     | 
    
         
             
                    File.unlink @options[:socket] if File.exists? @options[:socket]
         
     | 
| 
       79 
124 
     | 
    
         
             
                    @options[:sockets] ||= []
         
     | 
| 
       80 
125 
     | 
    
         
             
                    @options[:sockets] << UNIXServer.new(@options[:socket])
         
     | 
| 
      
 126 
     | 
    
         
            +
                    @logger.info "Now listening on UNIX Socket: #{@options[:socket]}"
         
     | 
| 
       81 
127 
     | 
    
         
             
                  end
         
     | 
| 
       82 
128 
     | 
    
         | 
| 
       83 
129 
     | 
    
         
             
                  #UDP potentially unsafe user monitor server for Authenticated Connections (TODO)
         
     | 
| 
         @@ -86,28 +132,39 @@ module Updater 
     | 
|
| 
       86 
132 
     | 
    
         
             
                    udp = UDPSocket.new
         
     | 
| 
       87 
133 
     | 
    
         
             
                    udp.bind(@options[:host],@options[:udp])
         
     | 
| 
       88 
134 
     | 
    
         
             
                    @options[:sockets] << udp
         
     | 
| 
      
 135 
     | 
    
         
            +
                    @logger.info "Now listening for UDP: #{@options[:host]}:#{@options[:udp]}"
         
     | 
| 
       89 
136 
     | 
    
         
             
                  end
         
     | 
| 
       90 
137 
     | 
    
         | 
| 
       91 
138 
     | 
    
         
             
                  #TCP Unsafe user monitor server for Authenticated Connections (TODO)
         
     | 
| 
       92 
139 
     | 
    
         
             
                  if @options[:tcp]
         
     | 
| 
       93 
140 
     | 
    
         
             
                    @options[:sockets] ||= []
         
     | 
| 
       94 
141 
     | 
    
         
             
                    @options[:sockets] << TCPServer.new(@options[:host],@options[:tcp])
         
     | 
| 
      
 142 
     | 
    
         
            +
                    @logger.info "Now listening for TCP: #{@options[:host]}:#{@options[:tcp]}"
         
     | 
| 
       95 
143 
     | 
    
         
             
                  end
         
     | 
| 
       96 
144 
     | 
    
         | 
| 
       97 
145 
     | 
    
         
             
                  #Log PID
         
     | 
| 
       98 
146 
     | 
    
         
             
                  File.open(@options[:pid_file],'w') { |f| f.write(Process.pid.to_s)}
         
     | 
| 
      
 147 
     | 
    
         
            +
                  
         
     | 
| 
      
 148 
     | 
    
         
            +
                  client_setup
         
     | 
| 
      
 149 
     | 
    
         
            +
                  
         
     | 
| 
       99 
150 
     | 
    
         
             
                  #start Worker
         
     | 
| 
       100 
     | 
    
         
            -
                   
     | 
| 
       101 
     | 
    
         
            -
                   
     | 
| 
      
 151 
     | 
    
         
            +
                  worker = @options[:worker] || 'fork'  #todo make this line windows safe
         
     | 
| 
      
 152 
     | 
    
         
            +
                  require "updater/#{worker}_worker"
         
     | 
| 
      
 153 
     | 
    
         
            +
                  worker_class = Updater.const_get("#{worker.capitalize}Worker")
         
     | 
| 
       102 
154 
     | 
    
         
             
                  worker_class.logger = @logger
         
     | 
| 
      
 155 
     | 
    
         
            +
                  @logger.info "Using #{worker_class.to_s} to run jobs:"
         
     | 
| 
       103 
156 
     | 
    
         
             
                  worker_class.start(@options)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  File.unlink(@options[:pid_file])
         
     | 
| 
      
 158 
     | 
    
         
            +
                  File.unlink @options[:socket] if @options[:socket] && File.exists?(@options[:socket])
         
     | 
| 
       104 
159 
     | 
    
         
             
                end
         
     | 
| 
       105 
160 
     | 
    
         | 
| 
       106 
161 
     | 
    
         
             
                def load_file(file)
         
     | 
| 
       107 
162 
     | 
    
         
             
                  return {} if file.nil?
         
     | 
| 
       108 
163 
     | 
    
         
             
                  file = File.open(file) if file.kind_of?(String)
         
     | 
| 
       109 
164 
     | 
    
         
             
                  @config_file = File.expand_path(file.path)
         
     | 
| 
       110 
     | 
    
         
            -
                  YAML.load(ERB.new( 
     | 
| 
      
 165 
     | 
    
         
            +
                  YAML.load(ERB.new(file.read).result(binding)) || {}
         
     | 
| 
      
 166 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 167 
     | 
    
         
            +
                  file.close
         
     | 
| 
       111 
168 
     | 
    
         
             
                end
         
     | 
| 
       112 
169 
     | 
    
         
             
              end
         
     | 
| 
       113 
170 
     | 
    
         
             
            end
         
     | 
    
        data/lib/updater/update.rb
    CHANGED
    
    | 
         @@ -22,7 +22,12 @@ module Updater 
     | 
|
| 
       22 
22 
     | 
    
         
             
                  ensure
         
     | 
| 
       23 
23 
     | 
    
         
             
                    run_chain :success if ret
         
     | 
| 
       24 
24 
     | 
    
         
             
                    run_chain :ensure
         
     | 
| 
       25 
     | 
    
         
            -
                     
     | 
| 
      
 25 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 26 
     | 
    
         
            +
                      @orm.destroy unless @orm.persistant
         
     | 
| 
      
 27 
     | 
    
         
            +
                    rescue DataObjects::ConnectionError
         
     | 
| 
      
 28 
     | 
    
         
            +
                      sleep 0.1
         
     | 
| 
      
 29 
     | 
    
         
            +
                      retry
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
       26 
31 
     | 
    
         
             
                  end
         
     | 
| 
       27 
32 
     | 
    
         
             
                  ret
         
     | 
| 
       28 
33 
     | 
    
         
             
                end
         
     | 
| 
         @@ -33,7 +38,7 @@ module Updater 
     | 
|
| 
       33 
38 
     | 
    
         | 
| 
       34 
39 
     | 
    
         
             
                def target
         
     | 
| 
       35 
40 
     | 
    
         
             
                  target = @orm.finder.nil? ? @orm.target : @orm.target.send(@orm.finder,@orm.finder_args)
         
     | 
| 
       36 
     | 
    
         
            -
                  raise TargetMissingError, "Class:'#{@orm.target}' Finder:'#{@orm.finder}', Args:'#{@orm.finder_args.inspect}'" unless target
         
     | 
| 
      
 41 
     | 
    
         
            +
                  raise TargetMissingError, "Target missing --Class:'#{@orm.target}' Finder:'#{@orm.finder}', Args:'#{@orm.finder_args.inspect}'" unless target
         
     | 
| 
       37 
42 
     | 
    
         
             
                  target
         
     | 
| 
       38 
43 
     | 
    
         
             
                end
         
     | 
| 
       39 
44 
     | 
    
         | 
| 
         @@ -49,17 +54,23 @@ module Updater 
     | 
|
| 
       49 
54 
     | 
    
         
             
                  @orm.name
         
     | 
| 
       50 
55 
     | 
    
         
             
                end
         
     | 
| 
       51 
56 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                #This is the appropriate  
     | 
| 
      
 57 
     | 
    
         
            +
                #This is the appropriate value to use for a chanable field value
         
     | 
| 
       53 
58 
     | 
    
         
             
                def id
         
     | 
| 
       54 
59 
     | 
    
         
             
                  @orm.id
         
     | 
| 
       55 
60 
     | 
    
         
             
                end
         
     | 
| 
       56 
61 
     | 
    
         | 
| 
      
 62 
     | 
    
         
            +
                def ==(other)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  id = other.id
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
                
         
     | 
| 
       57 
66 
     | 
    
         
             
                def persistant?
         
     | 
| 
       58 
67 
     | 
    
         
             
                  @orm.persistant
         
     | 
| 
       59 
68 
     | 
    
         
             
                end
         
     | 
| 
       60 
69 
     | 
    
         | 
| 
       61 
70 
     | 
    
         
             
                def inspect
         
     | 
| 
       62 
71 
     | 
    
         
             
                  "#<Updater::Update target=#{target.inspect} time=#{orm.time}>"
         
     | 
| 
      
 72 
     | 
    
         
            +
                rescue TargetMissingError
         
     | 
| 
      
 73 
     | 
    
         
            +
                  "#<Updater::Update target=<missing> time=#{orm.time}>"
         
     | 
| 
       63 
74 
     | 
    
         
             
                end
         
     | 
| 
       64 
75 
     | 
    
         | 
| 
       65 
76 
     | 
    
         
             
              private
         
     | 
| 
         @@ -93,6 +104,9 @@ module Updater 
     | 
|
| 
       93 
104 
     | 
    
         
             
                  chains.each do |job|
         
     | 
| 
       94 
105 
     | 
    
         
             
                    Update.new(job.target).run(self,job.params)
         
     | 
| 
       95 
106 
     | 
    
         
             
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                rescue NameError
         
     | 
| 
      
 108 
     | 
    
         
            +
                  puts @orm.inspect
         
     | 
| 
      
 109 
     | 
    
         
            +
                  raise
         
     | 
| 
       96 
110 
     | 
    
         
             
                end
         
     | 
| 
       97 
111 
     | 
    
         | 
| 
       98 
112 
     | 
    
         
             
                class << self
         
     | 
| 
         @@ -100,6 +114,16 @@ module Updater 
     | 
|
| 
       100 
114 
     | 
    
         
             
                  #This attribute must be set to some ORM that will persist the data
         
     | 
| 
       101 
115 
     | 
    
         
             
                  attr_accessor :orm
         
     | 
| 
       102 
116 
     | 
    
         | 
| 
      
 117 
     | 
    
         
            +
                  #remove once Bug is discovered
         
     | 
| 
      
 118 
     | 
    
         
            +
                  def orm=(input)
         
     | 
| 
      
 119 
     | 
    
         
            +
                    raise ArgumentError, "Must set ORM to and appropriate class" unless input.kind_of? Class
         
     | 
| 
      
 120 
     | 
    
         
            +
                    @orm = input
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
                  
         
     | 
| 
      
 123 
     | 
    
         
            +
                  # This is an open IO socket that will be writen to when a job is scheduled. If it is unset
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # then @pid is signaled instead.
         
     | 
| 
      
 125 
     | 
    
         
            +
                  attr_accessor :socket
         
     | 
| 
      
 126 
     | 
    
         
            +
                  
         
     | 
| 
       103 
127 
     | 
    
         
             
                  #Gets a single job form the queue, locks and runs it.  it returns the number of second
         
     | 
| 
       104 
128 
     | 
    
         
             
                  #Until the next job is scheduled, or 0 is there are more current jobs, or nil if there 
         
     | 
| 
       105 
129 
     | 
    
         
             
                  #are no jobs scheduled.
         
     | 
| 
         @@ -198,8 +222,12 @@ module Updater 
     | 
|
| 
       198 
222 
     | 
    
         
             
                  # Advanced: This method allows values to be passed directly to the ORM layer's create method.
         
     | 
| 
       199 
223 
     | 
    
         
             
                  # use +at+ and friends for everyday use cases.
         
     | 
| 
       200 
224 
     | 
    
         
             
                  def schedule(hash)
         
     | 
| 
       201 
     | 
    
         
            -
                    new(@orm.create(hash))
         
     | 
| 
      
 225 
     | 
    
         
            +
                    r = new(@orm.create(hash))
         
     | 
| 
       202 
226 
     | 
    
         
             
                    signal_worker
         
     | 
| 
      
 227 
     | 
    
         
            +
                    r
         
     | 
| 
      
 228 
     | 
    
         
            +
                  rescue NoMethodError
         
     | 
| 
      
 229 
     | 
    
         
            +
                    raise ArgumentError, "ORM not initialized!" if @orm.nil?
         
     | 
| 
      
 230 
     | 
    
         
            +
                    raise
         
     | 
| 
       203 
231 
     | 
    
         
             
                  end
         
     | 
| 
       204 
232 
     | 
    
         | 
| 
       205 
233 
     | 
    
         
             
                  # Create a new job having the same charistics as the old, except that 'hash' will override the original.
         
     | 
| 
         @@ -237,7 +265,9 @@ module Updater 
     | 
|
| 
       237 
265 
     | 
    
         
             
                  #
         
     | 
| 
       238 
266 
     | 
    
         
             
                  # <Array[Updater]> unless name is given then only a single [Updater] instance. 
         
     | 
| 
       239 
267 
     | 
    
         
             
                  def for(target,name=nil)
         
     | 
| 
       240 
     | 
    
         
            -
                     
     | 
| 
      
 268 
     | 
    
         
            +
                    target,finder,args = target_for(target)
         
     | 
| 
      
 269 
     | 
    
         
            +
                    ret = @orm.for(target,finder,args,name).map {|i| new(i)}
         
     | 
| 
      
 270 
     | 
    
         
            +
                    name ? ret.first : ret
         
     | 
| 
       241 
271 
     | 
    
         
             
                  end
         
     | 
| 
       242 
272 
     | 
    
         | 
| 
       243 
273 
     | 
    
         
             
                        #The time class used by Updater.  See time= 
         
     | 
| 
         @@ -286,6 +316,8 @@ module Updater 
     | 
|
| 
       286 
316 
     | 
    
         
             
                  #is set then an attempt will be made to signal the worker any
         
     | 
| 
       287 
317 
     | 
    
         
             
                  #time a new update is made.
         
     | 
| 
       288 
318 
     | 
    
         
             
                  #
         
     | 
| 
      
 319 
     | 
    
         
            +
                  #The PID will not be signaled if @socket is availible, but should be set as a back-up
         
     | 
| 
      
 320 
     | 
    
         
            +
                  #
         
     | 
| 
       289 
321 
     | 
    
         
             
                  #If pid is not set, or is set to nil then the scheduleing program 
         
     | 
| 
       290 
322 
     | 
    
         
             
                  #is responcible for waking-up a potentially sleeping worker process
         
     | 
| 
       291 
323 
     | 
    
         
             
                  #in another way.
         
     | 
| 
         @@ -295,6 +327,7 @@ module Updater 
     | 
|
| 
       295 
327 
     | 
    
         
             
                    Process::kill 0, @pid
         
     | 
| 
       296 
328 
     | 
    
         
             
                    @pid
         
     | 
| 
       297 
329 
     | 
    
         
             
                  rescue Errno::ESRCH, ArgumentError
         
     | 
| 
      
 330 
     | 
    
         
            +
                    @pid = nil
         
     | 
| 
       298 
331 
     | 
    
         
             
                    raise ArgumentError, "PID was invalid"
         
     | 
| 
       299 
332 
     | 
    
         
             
                  end
         
     | 
| 
       300 
333 
     | 
    
         | 
| 
         @@ -304,7 +337,9 @@ module Updater 
     | 
|
| 
       304 
337 
     | 
    
         | 
| 
       305 
338 
     | 
    
         
             
                private
         
     | 
| 
       306 
339 
     | 
    
         
             
                  def signal_worker
         
     | 
| 
       307 
     | 
    
         
            -
                    if @ 
     | 
| 
      
 340 
     | 
    
         
            +
                    if @socket
         
     | 
| 
      
 341 
     | 
    
         
            +
                      @socket.write '.'
         
     | 
| 
      
 342 
     | 
    
         
            +
                    elsif @pid
         
     | 
| 
       308 
343 
     | 
    
         
             
                      Process::kill "USR2", @pid
         
     | 
| 
       309 
344 
     | 
    
         
             
                    end
         
     | 
| 
       310 
345 
     | 
    
         
             
                  end
         
     | 
    
        data/spec/named_request_spec.rb
    CHANGED
    
    | 
         @@ -8,29 +8,49 @@ describe "named request" do 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
              before(:each) do
         
     | 
| 
       10 
10 
     | 
    
         
             
                Foo.all.destroy!
         
     | 
| 
      
 11 
     | 
    
         
            +
                Update.clear_all
         
     | 
| 
       11 
12 
     | 
    
         
             
              end
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
14 
     | 
    
         
             
              it "should be found by name when target is an instance" do
         
     | 
| 
       14 
15 
     | 
    
         
             
                f = Foo.create(:name=>'Honey')
         
     | 
| 
       15 
16 
     | 
    
         
             
                u = Update.immidiate(f,:bar,[:named],:name=>'Now')
         
     | 
| 
       16 
17 
     | 
    
         
             
                u.name.should ==("Now")
         
     | 
| 
       17 
     | 
    
         
            -
                pending "'for' not implemented"
         
     | 
| 
       18 
18 
     | 
    
         
             
                Update.for(f, "Now").should ==(u)
         
     | 
| 
       19 
19 
     | 
    
         
             
              end
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
              it "should be found by name when target is a class" do
         
     | 
| 
       22 
22 
     | 
    
         
             
                u = Update.immidiate(Foo,:bar,[:named],:name=>'Now')
         
     | 
| 
       23 
23 
     | 
    
         
             
                u.name.should ==("Now")
         
     | 
| 
       24 
     | 
    
         
            -
                pending "'for' not implemented"
         
     | 
| 
       25 
24 
     | 
    
         
             
                Update.for(Foo, "Now").should ==(u)
         
     | 
| 
       26 
25 
     | 
    
         
             
              end
         
     | 
| 
       27 
26 
     | 
    
         | 
| 
       28 
27 
     | 
    
         
             
              it "should return all updates for a given target" do
         
     | 
| 
       29 
     | 
    
         
            -
                u1 = Update.immidiate(Foo,:bar,[:arg1,:arg2])
         
     | 
| 
      
 28 
     | 
    
         
            +
                u1 = Update.immidiate(Foo,:bar,[:arg1,:arg2], :name=>'First')
         
     | 
| 
       30 
29 
     | 
    
         
             
                u2 = Update.immidiate(Foo,:bar,[:arg3,:arg4])
         
     | 
| 
       31 
     | 
    
         
            -
                pending "'for' not implemented"
         
     | 
| 
       32 
30 
     | 
    
         
             
                Update.for(Foo).should include(u1,u2)
         
     | 
| 
       33 
31 
     | 
    
         
             
              end
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 32 
     | 
    
         
            +
              
         
     | 
| 
      
 33 
     | 
    
         
            +
              #locked updates are already running and can therefore not be modified
         
     | 
| 
      
 34 
     | 
    
         
            +
              it "should not include locked updates" do
         
     | 
| 
      
 35 
     | 
    
         
            +
                u = Update.immidiate(Foo,:bar,[:named],:name=>'Now')
         
     | 
| 
      
 36 
     | 
    
         
            +
                u.orm.lock(Struct.new(:name).new('test_worker'))
         
     | 
| 
      
 37 
     | 
    
         
            +
                u.orm.should be_locked
         
     | 
| 
      
 38 
     | 
    
         
            +
                Update.for(Foo).should_not include(u)
         
     | 
| 
      
 39 
     | 
    
         
            +
                Update.for(Foo).should be_empty
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
              
         
     | 
| 
      
 42 
     | 
    
         
            +
              it "should not return rusults with the wrong name" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                u = Update.immidiate(Foo,:bar,[:named],:name=>'Now')
         
     | 
| 
      
 44 
     | 
    
         
            +
                u.name.should ==("Now")
         
     | 
| 
      
 45 
     | 
    
         
            +
                Update.for(Foo, "Then").should be_nil
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
              
         
     | 
| 
      
 48 
     | 
    
         
            +
              it "should not return results for the wring target" do
         
     | 
| 
      
 49 
     | 
    
         
            +
                f = Foo.create(:name=>'Honey')
         
     | 
| 
      
 50 
     | 
    
         
            +
                g = Foo.create(:name=>'Sweetie Pie')
         
     | 
| 
      
 51 
     | 
    
         
            +
                u = Update.immidiate(f,:bar,[:named],:name=>'Now')
         
     | 
| 
      
 52 
     | 
    
         
            +
                Update.for(f).should include(u)
         
     | 
| 
      
 53 
     | 
    
         
            +
                Update.for(g).should be_empty
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
       35 
55 
     | 
    
         | 
| 
       36 
56 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification 
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: updater
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.9.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors: 
         
     | 
| 
       7 
7 
     | 
    
         
             
            - John F. Miller
         
     | 
| 
         @@ -9,7 +9,7 @@ autorequire: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
            date: 2010- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2010-03-26 00:00:00 -07:00
         
     | 
| 
       13 
13 
     | 
    
         
             
            default_executable: 
         
     | 
| 
       14 
14 
     | 
    
         
             
            dependencies: 
         
     | 
| 
       15 
15 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     |