Class: Woods::Unblocked::RateLimiter

Inherits:
Object
  • Object
show all
Defined in:
lib/woods/unblocked/rate_limiter.rb

Overview

Daily budget-based rate limiter for the Unblocked API (1000 calls/day).

Unlike Notion’s per-second throttling, Unblocked limits by daily call count. Tracks usage against a configurable budget, warns when approaching the limit, and raises when exhausted.

Examples:

limiter = RateLimiter.new(daily_budget: 1000)
limiter.track { client.put_document(...) }  # => result
limiter.remaining                            # => 999

Constant Summary collapse

DEFAULT_BUDGET =
1000
WARN_THRESHOLD =

Warn at 80% usage

0.8

Instance Method Summary collapse

Constructor Details

#initialize(daily_budget: DEFAULT_BUDGET, warn_io: $stderr) ⇒ RateLimiter

Returns a new instance of RateLimiter.

Parameters:

  • daily_budget (Integer) (defaults to: DEFAULT_BUDGET)

    Maximum API calls per day

  • warn_io (IO) (defaults to: $stderr)

    Where to write warnings (default: $stderr)



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/woods/unblocked/rate_limiter.rb', line 22

def initialize(daily_budget: DEFAULT_BUDGET, warn_io: $stderr)
  unless daily_budget.is_a?(Integer) && daily_budget.positive?
    raise ArgumentError, 'daily_budget must be positive'
  end

  @daily_budget = daily_budget
  @calls_today = 0
  @warn_io = warn_io
  @warned = false
  @mutex = Mutex.new
end

Instance Method Details

#remainingInteger

Number of API calls remaining in the daily budget.

Returns:

  • (Integer)


59
60
61
# File 'lib/woods/unblocked/rate_limiter.rb', line 59

def remaining
  @daily_budget - @calls_today
end

#reset!void

This method returns an undefined value.

Reset the daily counter (for testing or manual reset).



73
74
75
76
77
78
# File 'lib/woods/unblocked/rate_limiter.rb', line 73

def reset!
  @mutex.synchronize do
    @calls_today = 0
    @warned = false
  end
end

#track { ... } ⇒ Object

Execute a block, tracking the API call against the daily budget.

Yields:

  • The API call to execute

Returns:

  • (Object)

    The block’s return value

Raises:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/woods/unblocked/rate_limiter.rb', line 39

def track
  raise ArgumentError, 'block required' unless block_given?

  @mutex.synchronize do
    if @calls_today >= @daily_budget
      raise Woods::Error,
            "Unblocked API daily budget exhausted (#{@daily_budget} calls). " \
            'Budget resets at midnight PST. Use UNBLOCKED_DAILY_BUDGET to adjust.'
    end

    @calls_today += 1
    warn_if_approaching_limit
  end

  yield
end

#usedInteger

Number of API calls used today.

Returns:

  • (Integer)


66
67
68
# File 'lib/woods/unblocked/rate_limiter.rb', line 66

def used
  @calls_today
end