Class: TgVizor::Transport

Inherits:
Object
  • Object
show all
Defined in:
lib/tgvizor/transport.rb

Overview

HTTP transport for sending event batches to the ingestion API.

Uses Net::HTTP from stdlib (zero runtime deps). Retries with exponential backoff + jitter on 5xx, 429, and network failures. Treats 4xx other than 429 as non-retryable (bad request, unauthorized — caller’s fault).

Defined Under Namespace

Classes: Result

Constant Summary collapse

OPEN_TIMEOUT =

seconds

5
READ_TIMEOUT =

seconds

10

Instance Method Summary collapse

Constructor Details

#initialize(endpoint:, api_key:, max_retries: 5, debug: false, logger: nil) ⇒ Transport

Returns a new instance of Transport.



31
32
33
34
35
36
37
# File 'lib/tgvizor/transport.rb', line 31

def initialize(endpoint:, api_key:, max_retries: 5, debug: false, logger: nil)
  @uri         = URI.join(endpoint.chomp("/") + "/", "v1/events")
  @api_key     = api_key
  @max_retries = max_retries
  @debug       = debug
  @logger      = logger
end

Instance Method Details

#send_batch(events) ⇒ Result

Send a batch of events.

Parameters:

  • events (Array<Hash>)

    queued events

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/tgvizor/transport.rb', line 42

def send_batch(events)
  body = JSON.generate(events: events)

  # One HTTP connection across all retries — saves a TCP+TLS handshake
  # (~150-300ms) on every retry attempt and lets keep-alive coalesce
  # follow-up batches in the same flush.
  http = build_http
  http.start

  begin
    (0..@max_retries).each do |attempt|
      sleep(backoff_seconds(attempt)) if attempt.positive?

      result = attempt_send(http, body, attempt)
      return result if result

      # nil result means retryable — loop continues
    end

    Result.new(ok: false, retryable: true, message: "max retries exceeded")
  ensure
    http.finish if http.started?
  end
end