Class: Ksef::Sessions::Status

Inherits:
Object
  • Object
show all
Defined in:
lib/ksef/sessions/status.rb

Overview

Reading session and invoice status, and waiting for it (docs/REFERENCE.md §12).

Single-shot calls are always available; the blocking helpers are built on them. Parsing lives in SessionState and InvoiceState, so this class is only the HTTP calls and the waiting.

Which endpoint to poll, and why it matters

GET /sessions — the list — is the tightest budget in the whole API at 10 req/min (§6.1), against 1200/h for GET /sessions/{ref} and the per-invoice endpoint. Polling must never touch the list. This class exposes no list call at all, which is the simplest way to make that mistake impossible rather than merely discouraged.

Backoff, and why not the reference clients' schedule

Capped exponential — 1s, 2s, 4s … 30s — with a five-minute deadline (DESIGN.md §6.5). Both official clients instead poll at a fixed 1 second for up to 60 attempts (§12.2). That is fine for a test utility and wrong for a library: at 1/s a single wait spends 60 of the 1200 requests an hour a context gets, and a 60-second ceiling is far too short for a large session. Their terminal condition is adopted, with one correction — see InvoiceCodes on why 100 also means keep going.

Constant Summary collapse

INITIAL_INTERVAL =

Seconds. Doubling from the first, clamped at the third.

1
BACKOFF_FACTOR =
2
MAX_INTERVAL =
30
DEFAULT_DEADLINE =

Overall wall-clock budget for a blocking wait.

300

Instance Method Summary collapse

Constructor Details

#initialize(connection, credential) ⇒ Status

Returns a new instance of Status.

Parameters:



37
38
39
40
# File 'lib/ksef/sessions/status.rb', line 37

def initialize(connection, credential)
  @connection = connection
  @credential = credential
end

Instance Method Details

#invoice(session_reference, invoice_reference) ⇒ InvoiceState

Returns:



50
51
52
53
54
55
# File 'lib/ksef/sessions/status.rb', line 50

def invoice(session_reference, invoice_reference)
  session_number = Sessions.reference_number!(session_reference)
  invoice_number = Sessions.reference_number!(invoice_reference)

  InvoiceState.from(get("sessions/#{session_number}/invoices/#{invoice_number}").body)
end

#session(reference) ⇒ SessionState

Returns:



43
44
45
46
47
# File 'lib/ksef/sessions/status.rb', line 43

def session(reference)
  number = Sessions.reference_number!(reference)

  SessionState.from(get("sessions/#{number}").body, number)
end

#wait_for_invoice(session_reference, invoice_reference) ⇒ Object

Polls one invoice until it stops being in progress.

Raises:



71
72
73
# File 'lib/ksef/sessions/status.rb', line 71

def wait_for_invoice(session_reference, invoice_reference, **, &)
  poll(-> { invoice(session_reference, invoice_reference) }, "invoice #{invoice_reference}", **, &)
end

#wait_for_session(reference) {|state| ... } ⇒ Object

Polls a session until it stops being in progress.

This waits for 200, not for 170: closing starts asynchronous UPO generation, so a wait that stopped at "closed" would return before the UPO existed.

Yield Parameters:

  • state (SessionState) —

    after each poll, for progress reporting

Raises:



64
65
66
# File 'lib/ksef/sessions/status.rb', line 64

def wait_for_session(reference, **, &)
  poll(-> { session(reference) }, "session #{reference}", **, &)
end

#wait_until_accepted(session_reference, invoice_reference) ⇒ InvoiceState

As #wait_for_invoice, but insists the invoice was accepted.

Returns:

Raises:



80
81
82
83
84
85
# File 'lib/ksef/sessions/status.rb', line 80

def wait_until_accepted(session_reference, invoice_reference, **, &)
  state = wait_for_invoice(session_reference, invoice_reference, **, &)
  return state if state.success?

  raise InvoiceRejectedError, rejection_message(state)
end