Class: Sinatra::AmpRepoMethods::DelayedGzipper

Inherits:
Object
  • Object
show all
Defined in:
lib/amp/server/extension/amp_extension.rb

Overview

DelayedGzipper

Takes a block when initialized, but doesn’t run the block. It actually saves the block, and then runs it later, streaming the results into a GZip stream. Very memory friendly.

This class is designed to work with Rack. All it has to do is implement an #each method which takes a block, and which calls that method when gzip data is to be written out. This way data doesn’t have to be generated, then processed, then processed, etc. It is actually streamed to the client.

Instance Method Summary collapse

Constructor Details

#initialize { ... } ⇒ DelayedGzipper

Creates a new DelayedGzipper. All you must do is create a new DelayedGzipper, whose block results in an IO-like object, and return it as the result of a Sinatra/Rack endpoint. Rack will run the #each method to stream the data out.

Yields:

  • The block provided will be stored and executed lazily later when the results of the block need to be generated and gzipped. Should return an IO-like object to maximize memory-friendliness.



204
205
206
# File 'lib/amp/server/extension/amp_extension.rb', line 204

def initialize(&block)
  @result_generator = block
end

Instance Method Details

#each(&block) ⇒ Object

For Rack compliance. The block should be called whenever data is to be written to the client. We actually save the block, and use a GzipWriter to funnel the gzipped data into the block. Pretty nifty.



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/amp/server/extension/amp_extension.rb', line 212

def each(&block)
  
  # Save the writer for safe-keeping
  @writer = block
  
  # This creates a gzip-writer. By passing in +self+ as the parameter, when we
  # write to the gzip-writer, it will then call #write on +self+ with the
  # gzipped data. This allows us to handle the compressed data immediately
  # instead of funneling it to a buffer or something useless like that.
  gzip  = ::Zlib::GzipWriter.new self
  gzip.mtime = Time.now
  
  # Gets the IO-like object that we need to gzip
  f = @result_generator.call
  
  begin
    chunk = f.read 4.kb
    gzip << chunk if chunk && chunk.any?
  end while chunk && chunk.any?
  
  # Finish it off
  gzip.close
  
  # We're done!
  @writer = nil
end

#write(data) ⇒ Object

Called by GzipWriter so we can immediately handle our gzipped data. We write it to the client using the @writer given to us in #each.

Parameters:

  • data (String)

    the data to write to the client. Gzipped.



244
245
246
# File 'lib/amp/server/extension/amp_extension.rb', line 244

def write(data)
  @writer.call data
end