Class: Restless::Uploader
- Inherits:
-
Object
- Object
- Restless::Uploader
- Defined in:
- lib/restless/uploader.rb
Overview
CONTRACT.md sections 8 (wire format) and 9 (batching).
Never raises to callers. Upload failures go to stderr under the debug flag and are otherwise swallowed: observability must not break the request path (SAFETY-004, SAFETY-008).
Constant Summary collapse
- BATCH_SIZE =
BATCH-001
10- FLUSH_INTERVAL_MS =
BATCH-002
5000- MAX_QUEUE =
BATCH-004
1000- HTTP_TIMEOUT_S =
10
Instance Attribute Summary collapse
-
#base_url ⇒ Object
readonly
Returns the value of attribute base_url.
-
#request_id_prefix ⇒ Object
readonly
Returns the value of attribute request_id_prefix.
Instance Method Summary collapse
- #api_key? ⇒ Boolean
-
#flush ⇒ Object
BATCH-005, BATCH-006, BATCH-007.
-
#initialize(api_key:, base_url:, request_id_prefix: nil, on_response: nil, transport: nil) ⇒ Uploader
constructor
A new instance of Uploader.
- #options ⇒ Object
- #push(captured) ⇒ Object
-
#warn_if_insecure ⇒ Object
WIRE-006.
Constructor Details
#initialize(api_key:, base_url:, request_id_prefix: nil, on_response: nil, transport: nil) ⇒ Uploader
Returns a new instance of Uploader.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/restless/uploader.rb', line 25 def initialize(api_key:, base_url:, request_id_prefix: nil, on_response: nil, transport: nil) @api_key = api_key.to_s @base_url = base_url.to_s @request_id_prefix = request_id_prefix @on_response = on_response # Test hook. Anything responding to # `call(url, headers, body) -> [status, body]`. @transport = transport @queue = [] @mutex = Mutex.new @timer = nil @inflight = [] warn_if_insecure end |
Instance Attribute Details
#base_url ⇒ Object (readonly)
Returns the value of attribute base_url.
23 24 25 |
# File 'lib/restless/uploader.rb', line 23 def base_url @base_url end |
#request_id_prefix ⇒ Object (readonly)
Returns the value of attribute request_id_prefix.
23 24 25 |
# File 'lib/restless/uploader.rb', line 23 def request_id_prefix @request_id_prefix end |
Instance Method Details
#api_key? ⇒ Boolean
43 44 45 |
# File 'lib/restless/uploader.rb', line 43 def api_key? !@api_key.empty? end |
#flush ⇒ Object
BATCH-005, BATCH-006, BATCH-007. Synchronous: resolves when the attempt completes.
88 89 90 91 92 93 |
# File 'lib/restless/uploader.rb', line 88 def flush batch = @mutex.synchronize { take_batch } upload(batch) unless batch.nil? || batch.empty? join_inflight nil end |
#options ⇒ Object
95 96 97 98 99 100 101 |
# File 'lib/restless/uploader.rb', line 95 def { base_url: @base_url, request_id_prefix: @request_id_prefix, has_api_key: api_key? } end |
#push(captured) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/restless/uploader.rb', line 61 def push(captured) # BATCH-008. return if Env.test_run? && !Env.setup_mode? batch = nil @mutex.synchronize do if @queue.length >= MAX_QUEUE # Drop the OLDEST. The newest entries are the ones an operator is # actively debugging. @queue.shift Env.debug_log("queue at #{MAX_QUEUE} -- dropping oldest captured request") end @queue << captured if flush_immediately? || @queue.length >= BATCH_SIZE batch = take_batch else start_timer end end upload_async(batch) if batch nil end |
#warn_if_insecure ⇒ Object
WIRE-006. The project key and every captured header would otherwise ship in the clear with no signal anywhere.
49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/restless/uploader.rb', line 49 def warn_if_insecure uri = URI.parse(@base_url) return unless uri.scheme == "http" return if %w[localhost 127.0.0.1].include?(uri.host) warn("[restless-sdk] RESTLESS_BASE_URL=#{@base_url} is plain HTTP -- your API " \ "key and every captured header will be transmitted unencrypted. " \ "Use https:// or localhost.") rescue StandardError nil end |