Class: Analysand::StreamingViewResponse

Inherits:
Object
  • Object
show all
Includes:
ResponseHeaders, StatusCodePredicates, Enumerable
Defined in:
lib/analysand/streaming_view_response.rb

Overview

Public: Controls streaming of view data.

This class is meant to be used by Analysand::Database#view. It exports the same interface as ViewResponse.

Examples:

resp = db.view('view/something', :stream => true)

resp.total_rows       # => 1000000
resp.offset           # => 0
resp.rows.take(100)   # => first 100 rows

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from StatusCodePredicates

#code, #conflict?, #not_found?, #success?, #unauthorized?

Methods included from ResponseHeaders

#cookies, #etag, #session_cookie

Constructor Details

#initializeStreamingViewResponse



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/analysand/streaming_view_response.rb', line 30

def initialize
  @reader = Fiber.new { yield self; "" }
  @generator = ViewStreaming::Builder.new

  # Analysand::Database#stream_view issues the request.  When the response
  # arrives, it yields control back here.  Subsequent resumes read the
  # body.
  #
  # We do this to provide the response headers as soon as possible.
  @reader.resume
end

Instance Attribute Details

#responseObject

Internal: The HTTP response.

This is set by Analysand::Database#stream_view. The #etag and #code methods use this for header information.



28
29
30
# File 'lib/analysand/streaming_view_response.rb', line 28

def response
  @response
end

Instance Method Details

#docsObject

Public: Yields documents in the view stream.

Note that #docs and #rows advance the same stream, so expect to miss half your rows if you do something like

resp.docs.zip(resp.rows)

If this is a problem for you, let me know and we can work out a solution.



50
51
52
# File 'lib/analysand/streaming_view_response.rb', line 50

def docs
  to_enum(:get_docs)
end

#eachObject



90
91
92
93
94
95
96
97
98
99
100
# File 'lib/analysand/streaming_view_response.rb', line 90

def each
  return to_enum unless block_given?

  while @reader.alive?
    read while @reader.alive? && @generator.staged_rows.empty?

    until @generator.staged_rows.empty?
      yield @generator.staged_rows.shift
    end
  end
end

#get_docsObject



54
55
56
# File 'lib/analysand/streaming_view_response.rb', line 54

def get_docs
  each { |r| yield r['doc'] if r.has_key?('doc') }
end

#get_keysObject



70
71
72
# File 'lib/analysand/streaming_view_response.rb', line 70

def get_keys
  each { |r| yield r['key'] if r.has_key?('key') }
end

#keysObject

Public: Yields document keys from the view stream.

Note that #keys and #rows advance the same stream, so expect to miss half your rows if you do something like

resp.keys.zip(resp.rows)

If this is a problem for you, let me know and we can work out a solution.



66
67
68
# File 'lib/analysand/streaming_view_response.rb', line 66

def keys
  to_enum(:get_keys)
end

#offsetObject



80
81
82
83
84
# File 'lib/analysand/streaming_view_response.rb', line 80

def offset
  read until @generator.offset

  @generator.offset
end

#readObject



86
87
88
# File 'lib/analysand/streaming_view_response.rb', line 86

def read
  @generator << @reader.resume
end

#rowsObject



102
103
104
# File 'lib/analysand/streaming_view_response.rb', line 102

def rows
  self
end

#total_rowsObject



74
75
76
77
78
# File 'lib/analysand/streaming_view_response.rb', line 74

def total_rows
  read until @generator.total_rows

  @generator.total_rows
end