equipoise 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de1fcce8a6fbfaed1a0009371d6350128ac310533cbbd52baf0f0883f8d9cdcf
4
- data.tar.gz: d2ea1aced1956bba17728d81a0677900010b4ad8d041397756bd8fd09b0459f6
3
+ metadata.gz: '0452669965e793163b574be7bec3312e057e7e93d959fd8fdc252adc53027d11'
4
+ data.tar.gz: 2da982746e503901ec54b261fb7845885fcc722c46ae03778388220632a68fc4
5
5
  SHA512:
6
- metadata.gz: d9a0dacc4037a20322ed758c1ee56999d50a8bde0585bb0e9bd47f4e363c52bdf0df121ef6b0d2bf4832705e54d2eb183633ebf15891333294cac45e1187de74
7
- data.tar.gz: 8808b757de5b892e82a106162c77372d7e9baafce7a67ac9162d362a5751cf65ee023db04430409d25a9e410730c0bf3f55b541446d5d1e61d03b8af2c2bd8da
6
+ metadata.gz: 300d97710b2ccde31122a986ecc53fb9f76c64c7040a0bd5e5199011cf383e73b27b5ada8f88e67720fde588af95715fa0d2cd71a535fb48869950809e04a723
7
+ data.tar.gz: 8b9a7a469777ab78cb8f0785d683643d72c24ee7951f013d6d003277593c6de5e36efede76bde0fddf6cb1f6bc09059352c623b87a078e796773443b32bbe286
data/CHANGELOG.md CHANGED
@@ -6,6 +6,26 @@ semantic versioning once published.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.0] - 2026-07-06
10
+
11
+ ### Added
12
+
13
+ - **Tunable transport limits with hard guardrails** (from AMP backfill feedback).
14
+ `read_timeout`, `max_retries`, and the new `batch_size` are configurable in the
15
+ `Equipoise.configure` block, but every value is clamped to a hard range so a
16
+ producer's config can never make the gem a bad citizen to the receiver:
17
+ - `read_timeout` → default raised to `30`s (headroom so a full-size batch
18
+ doesn't time out and get re-sent) and clamped to `5..120`s (a too-low timeout
19
+ is how one slow batch becomes two concurrent deliveries).
20
+ - `max_retries` → clamped to `0..5` (no retry storms).
21
+ - `batch_size` → clamped to `1..500` (the receiver's per-batch cap); drives the
22
+ default `contacts.batch_sync` chunk size, and an explicit `chunk_size:` is
23
+ clamped to the same ceiling.
24
+ Out-of-range values are clamped (and logged when a `logger` is set), never
25
+ raised, so a stray setting degrades to "safe" instead of failing boot.
26
+
27
+ ## [0.1.0] - 2026-07-05
28
+
9
29
  ### Added
10
30
 
11
31
  - **Activity / event ingestion** — `contacts.record_activity(external_id:,
@@ -24,7 +44,7 @@ semantic versioning once published.
24
44
  - **`Equipoise.disable!` / `enable!` / `disabled?`** test mode — when disabled,
25
45
  the client short-circuits to a no-op before any network call or validation,
26
46
  so a stray `EQUIPOISE_API_KEY` in a test env can't make a live call.
27
- - Initial producer client (External CRM Sync, S12):
47
+ - Initial producer client:
28
48
  - `Equipoise.configure` / `Equipoise.client` with env-based, rotation-aware
29
49
  credentials.
30
50
  - `client.contacts.sync` / `batch_sync` (chunks to 500, deterministic per-chunk
data/README.md CHANGED
@@ -9,17 +9,17 @@ tag reconciliation, custom-field coercion) lives server-side in the receiver's
9
9
  `Crm::ContactSyncService`. This client just handles auth, JSON, idempotency,
10
10
  bounded retry/backoff, and typed errors.
11
11
 
12
- - **Contract:** [`EXTERNAL_CRM_SYNC_API.openapi.yaml`](../../documentation/integrations/EXTERNAL_CRM_SYNC_API.openapi.yaml) (OpenAPI 3.1)
13
- - **Guide:** [`EXTERNAL_CRM_SYNC.md`](../../documentation/integrations/EXTERNAL_CRM_SYNC.md)
12
+ The API contract (OpenAPI 3.1) and integration guide are documented with your
13
+ Equipoise account at [app.equipoi.se](https://app.equipoi.se).
14
14
 
15
- > Pre-1.0 and unpublished consumed by AMP as a `path:`/git dependency first,
16
- > published to RubyGems only once proven.
15
+ > Pre-1.0: the client is stable and published to RubyGems, but the server API
16
+ > surface may still change before 1.0.
17
17
 
18
18
  ## Install
19
19
 
20
20
  ```ruby
21
21
  # In the producer app's Gemfile
22
- gem "equipoise", path: "../equipoise/gems/equipoise" # or git:
22
+ gem "equipoise"
23
23
  ```
24
24
 
25
25
  ## Configure
@@ -43,6 +43,24 @@ non-loopback host is refused, so the key is never sent in cleartext).
43
43
  Under Rails, run `rails g equipoise:install` to generate
44
44
  `config/initializers/equipoise.rb`.
45
45
 
46
+ ### Tuning (optional)
47
+
48
+ Three transport knobs are configurable and **clamped** to safe ranges, so a
49
+ producer's config can never make the client a bad citizen to the receiver — an
50
+ out-of-range value is clamped (and logged if a `logger` is set), never raised:
51
+
52
+ ```ruby
53
+ Equipoise.configure do |c|
54
+ c.read_timeout = 30 # seconds per request; clamped to 5..120
55
+ c.max_retries = 2 # transient-failure retries; clamped to 0..5
56
+ c.batch_size = 500 # contacts per batch_sync request; clamped to 1..500
57
+ end
58
+ ```
59
+
60
+ For a large `batch_sync` backfill, keep `read_timeout` comfortably above how long
61
+ one full batch takes server-side (or lower `batch_size`) so a slow batch never
62
+ times out and gets re-sent.
63
+
46
64
  ## Use
47
65
 
48
66
  ```ruby
@@ -57,7 +75,7 @@ Equipoise.client.contacts.sync(
57
75
  external_id: user.id, email: user.email, idempotency_key: request_id
58
76
  )
59
77
 
60
- # Batch backfill — chunks to 500/call, one bad item never fails the batch.
78
+ # Batch backfill — chunks to batch_size (default 500), one bad item never fails it.
61
79
  # It never raises mid-batch: per-item rejections and chunk-level transport
62
80
  # failures both come back as failed items, so earlier successes are preserved.
63
81
  result = Equipoise.client.contacts.batch_sync(
@@ -52,10 +52,10 @@ module Equipoise
52
52
  @custom_fields ||= CustomFields.new(self)
53
53
  end
54
54
 
55
- # Claude authored — the single request chokepoint. Returns a Response on
55
+ # The single request chokepoint. Returns a Response on
56
56
  # 2xx; raises a typed ApiError (or ConnectionError) otherwise.
57
57
  def request(method, path, body: nil, query: nil, headers: {})
58
- return null_response if config.disabled? # test-mode short-circuit (#5) — before validate! or any I/O
58
+ return null_response if config.disabled? # test-mode short-circuit — before validate! or any I/O
59
59
 
60
60
  config.validate!
61
61
  uri = build_uri(path, query)
@@ -18,6 +18,12 @@
18
18
  # the wire). Local dev (`http://localhost`) is allowed; set `allow_insecure_http`
19
19
  # to permit a trusted TLS-terminating internal endpoint.
20
20
  #
21
+ # Transport knobs (read_timeout, max_retries, batch_size) are producer-tunable in
22
+ # the configure block but CLAMPED to hard ranges (see *_BOUNDS) so a misconfig
23
+ # can never make the gem a bad citizen to the receiver — an oversized batch, a
24
+ # retry storm, or a too-eager give-up-and-retry. Out-of-range values are clamped
25
+ # (and logged if a logger is set), never raised.
26
+ #
21
27
  # Used by: Equipoise.configure, Equipoise::Client
22
28
  # =============================================================================
23
29
 
@@ -25,20 +31,38 @@ module Equipoise
25
31
  class Configuration
26
32
  DEFAULT_BASE_URL = "https://app.equipoi.se/api/v1"
27
33
  DEFAULT_OPEN_TIMEOUT = 5
28
- DEFAULT_READ_TIMEOUT = 15
34
+ DEFAULT_READ_TIMEOUT = 30
29
35
  DEFAULT_MAX_RETRIES = 2
36
+ DEFAULT_BATCH_SIZE = 500
37
+
38
+ # Hard limits — every producer-tunable transport knob is clamped into these
39
+ # ranges so a misconfigured producer can never punish the receiver:
40
+ # read_timeout — floor keeps the producer patient enough that one slow
41
+ # batch doesn't become two concurrent deliveries (a low timeout is how a
42
+ # retry double-submits); ceiling stops a producer worker hanging forever.
43
+ # max_retries — ceiling means a misconfig can't retry-storm the receiver.
44
+ # batch_size — ceiling is the receiver's own per-batch cap (it rejects
45
+ # anything larger); floor of 1 keeps slicing sane.
46
+ # Out-of-range values are clamped, not raised (see #clamp_to).
47
+ READ_TIMEOUT_BOUNDS = (5..120).freeze
48
+ MAX_RETRIES_BOUNDS = (0..5).freeze
49
+ BATCH_SIZE_BOUNDS = (1..500).freeze
50
+
30
51
  LOOPBACK_HOSTS = %w[localhost 127.0.0.1 ::1 [::1]].freeze
31
52
  PRODUCTION_HOST = URI.parse(DEFAULT_BASE_URL).host # "app.equipoi.se"
32
53
 
33
54
  attr_accessor :open_timeout,
34
- :read_timeout,
35
- :max_retries,
36
55
  :retry_backoff_base,
37
56
  :max_retry_backoff,
38
57
  :allow_insecure_http,
39
58
  :enabled,
40
59
  :logger,
41
60
  :user_agent
61
+ # Clamped knobs — custom writers (below) hold every override inside its
62
+ # *_BOUNDS so the gem stays a good citizen no matter what a producer sets.
63
+ attr_reader :read_timeout,
64
+ :max_retries,
65
+ :batch_size
42
66
  attr_writer :api_key,
43
67
  :base_url,
44
68
  :source
@@ -51,6 +75,7 @@ module Equipoise
51
75
  @open_timeout = DEFAULT_OPEN_TIMEOUT
52
76
  @read_timeout = DEFAULT_READ_TIMEOUT
53
77
  @max_retries = DEFAULT_MAX_RETRIES
78
+ @batch_size = DEFAULT_BATCH_SIZE
54
79
  @retry_backoff_base = 0.5
55
80
  @max_retry_backoff = 30
56
81
  @allow_insecure_http = false
@@ -59,14 +84,14 @@ module Equipoise
59
84
  @user_agent = "equipoise-ruby/#{Equipoise::VERSION}"
60
85
  end
61
86
 
62
- # — Claude authored — test-mode kill switch (#5). When disabled the client
87
+ # Test-mode kill switch. When disabled the client
63
88
  # short-circuits to a no-op before any network call OR validation, so a stray
64
89
  # EQUIPOISE_API_KEY in a producer's test env can never make a live call.
65
90
  def disabled?
66
91
  !enabled
67
92
  end
68
93
 
69
- # Claude authored — explicit assignment wins; otherwise read ENV each call
94
+ # Explicit assignment wins; otherwise read ENV each call
70
95
  # (rotation-aware).
71
96
  def api_key
72
97
  resolve(@api_key, "EQUIPOISE_API_KEY")
@@ -80,6 +105,32 @@ module Equipoise
80
105
  resolve(@source, "EQUIPOISE_SOURCE")
81
106
  end
82
107
 
108
+ # Clamped transport knobs. Each override is bounded to a
109
+ # hard range (see *_BOUNDS) so a producer's config can never make the gem a
110
+ # bad citizen to the receiver. An out-of-range value is clamped (and logged,
111
+ # if a logger is set) rather than raised, so a stray setting degrades to
112
+ # "safe" instead of crashing the producer's boot. read_timeout takes
113
+ # fractional seconds; the count knobs are whole numbers.
114
+ def read_timeout=(seconds)
115
+ @read_timeout = clamp_to(:read_timeout, seconds.to_f, READ_TIMEOUT_BOUNDS)
116
+ end
117
+
118
+ def max_retries=(count)
119
+ @max_retries = clamp_to(:max_retries, count.to_i, MAX_RETRIES_BOUNDS)
120
+ end
121
+
122
+ def batch_size=(size)
123
+ @batch_size = clamp_to(:batch_size, size.to_i, BATCH_SIZE_BOUNDS)
124
+ end
125
+
126
+ # The effective per-request chunk size: an explicit
127
+ # `batch_sync(chunk_size:)` wins, else the configured batch_size — but either
128
+ # way clamped to the receiver's hard cap so the gem never posts an oversized
129
+ # (and rejected) batch.
130
+ def bounded_batch_size(requested = nil)
131
+ clamp_to(:batch_size, (requested || batch_size).to_i, BATCH_SIZE_BOUNDS)
132
+ end
133
+
83
134
  def validate!
84
135
  raise ConfigurationError, "api_key is required (set EQUIPOISE_API_KEY or Equipoise.configure)" if api_key.to_s.empty?
85
136
  raise ConfigurationError, "base_url is required" if base_url.to_s.empty?
@@ -91,6 +142,17 @@ module Equipoise
91
142
 
92
143
  private
93
144
 
145
+ # Clamp a knob into its hard range; warn (never raise) so
146
+ # a misconfigured value is corrected in place instead of failing the
147
+ # producer's boot. A logger is optional, so the warning is best-effort.
148
+ def clamp_to(name, value, range)
149
+ bounded = value.clamp(range.min, range.max)
150
+ if bounded != value
151
+ logger&.warn("[equipoise] #{name}=#{value} is outside #{range.min}..#{range.max}; clamped to #{bounded}")
152
+ end
153
+ bounded
154
+ end
155
+
94
156
  def resolve(explicit, env_key)
95
157
  return explicit unless explicit.to_s.empty?
96
158
 
@@ -98,7 +160,7 @@ module Equipoise
98
160
  value.to_s.empty? ? nil : value
99
161
  end
100
162
 
101
- # Claude authored — never transmit the Bearer key in cleartext to a remote
163
+ # Never transmit the Bearer key in cleartext to a remote
102
164
  # host. https is always fine; http is allowed only for loopback dev or when
103
165
  # the producer explicitly opts in for a trusted internal endpoint.
104
166
  def ensure_secure_transport!
@@ -112,7 +174,7 @@ module Equipoise
112
174
  "Use https://, or set config.allow_insecure_http = true for a trusted internal endpoint."
113
175
  end
114
176
 
115
- # Claude authored (#3) — the key prefix encodes its environment (eq_test_ /
177
+ # The key prefix encodes its environment (eq_test_ /
116
178
  # eq_live_); refuse the dangerous host mismatches no producer can see coming:
117
179
  # a TEST key pointed at the production host (test creds writing the real CRM)
118
180
  # or a LIVE key pointed at localhost (prod creds in a dev loop). Staging and
@@ -20,13 +20,15 @@
20
20
 
21
21
  module Equipoise
22
22
  class Contacts
23
- BATCH_LIMIT = 500
23
+ # The receiver's hard per-batch cap. Kept for back-compat; the effective
24
+ # chunk size now comes from config.batch_size (clamped to this).
25
+ BATCH_LIMIT = Configuration::BATCH_SIZE_BOUNDS.max # 500
24
26
 
25
27
  def initialize(client)
26
28
  @client = client
27
29
  end
28
30
 
29
- # Claude authored — upsert one contact by (source, external_id). Unknown
31
+ # Upsert one contact by (source, external_id). Unknown
30
32
  # attributes (email/name/first_name/last_name/phone/tags/custom_fields/
31
33
  # create_missing_fields) pass straight through; nils are dropped.
32
34
  def sync(external_id:, source: nil, idempotency_key: nil, **attributes)
@@ -38,35 +40,40 @@ module Equipoise
38
40
  @client.request(:post, "/contacts/sync", body: payload, headers: headers)
39
41
  end
40
42
 
41
- # Claude authored — upsert many contacts. Chunks to ≤500/call and returns a
42
- # BatchResult aggregating every per-item result across chunks. It NEVER raises
43
+ # Upsert many contacts. Chunks to the configured
44
+ # batch_size (default 500, hard-capped at the receiver's per-batch limit) and
45
+ # returns a BatchResult aggregating every per-item result across chunks. Pass
46
+ # chunk_size: to override per call — it is clamped to the same hard cap, so a
47
+ # caller can never post an oversized (and rejected) batch. It NEVER raises
43
48
  # mid-batch: a per-item server rejection comes back as an `ok: false` item
44
49
  # (the receiver returns 200 per chunk), and a chunk-level transport/HTTP
45
50
  # failure marks that chunk's records failed so earlier chunks' successes are
46
51
  # preserved and the producer can retry only the failures.
47
- def batch_sync(records, source: nil, chunk_size: BATCH_LIMIT)
48
- default_source = source || @client.config.source
52
+ def batch_sync(records, source: nil, chunk_size: nil)
53
+ config = @client.config
54
+ default_source = source || config.source
49
55
  prepared = records.map { |record| prepare_record(record, default_source) }
50
56
  ensure_sources!(prepared)
51
57
 
52
- items = []
53
- prepared.each_slice(chunk_size) { |chunk| items.concat(sync_chunk(chunk)) }
58
+ slice_size = config.bounded_batch_size(chunk_size)
59
+ items = []
60
+ prepared.each_slice(slice_size) { |chunk| items.concat(sync_chunk(chunk)) }
54
61
  BatchResult.new(items)
55
62
  end
56
63
 
57
- # Claude authored — deactivate the external link; the Contact is retained.
64
+ # Deactivate the external link; the Contact is retained.
58
65
  def deactivate(external_id:, source: nil)
59
66
  @client.request(:post, "#{sync_path(external_id)}/deactivate",
60
67
  query: { source: resolve_source(source) })
61
68
  end
62
69
 
63
- # Claude authored — read back the Contact linked to (source, external_id).
70
+ # Read back the Contact linked to (source, external_id).
64
71
  def find(external_id:, source: nil)
65
72
  @client.request(:get, sync_path(external_id),
66
73
  query: { source: resolve_source(source) })
67
74
  end
68
75
 
69
- # Claude authored — record an external event on the contact's timeline.
76
+ # Record an external event on the contact's timeline.
70
77
  # `event_type: "subscribed"`/`"unsubscribed"` toggles the contact's email
71
78
  # subscription (state + activity); any other event_type logs a generic
72
79
  # timeline event. `metadata` is a free-form hash of producer context.
@@ -32,7 +32,7 @@ module Equipoise
32
32
  @client.request(:get, field_path(key), query: query)
33
33
  end
34
34
 
35
- # — Claude authored — create-or-update a field by key (server returns 201 vs
35
+ # Create-or-update a field by key (server returns 201 vs
36
36
  # 200). `customizable_type` from the body is ignored server-side (defaults to
37
37
  # Contact); a client can't declare fields on arbitrary owner types.
38
38
  def declare(key:, **attributes)
@@ -25,7 +25,7 @@
25
25
 
26
26
  module Equipoise
27
27
  class Error < StandardError
28
- # Claude authored — the retry taxonomy lives in the gem so no producer has
28
+ # The retry taxonomy lives in the gem so no producer has
29
29
  # to memorize which failures are transient. Base default: not retryable.
30
30
  # A producer's job becomes: `rescue Equipoise::Error => e; raise if e.retryable?`.
31
31
  def retryable?
@@ -59,7 +59,7 @@ module Equipoise
59
59
  status == 429 || status.to_i >= 500
60
60
  end
61
61
 
62
- # Claude authored — pick the subclass by HTTP status and parse the error
62
+ # Pick the subclass by HTTP status and parse the error
63
63
  # envelope. Robust to an empty body (401) and the legacy string error body.
64
64
  def self.from_response(response)
65
65
  status = response.status
@@ -26,7 +26,7 @@
26
26
  # (override `equipoise_sync!` to enqueue) so a web request never blocks on the
27
27
  # round-trip. In dev, ensure the queue runs inline or the post never fires.
28
28
  #
29
- # Producer-side firing is exercised in AMP (S13); the gem suite tests the
29
+ # Producer-side firing is exercised in AMP; the gem suite tests the
30
30
  # transport methods directly.
31
31
  #
32
32
  # Used by: producer models that opt in (e.g. AMP's User)
@@ -14,7 +14,7 @@ module Equipoise
14
14
  module Util
15
15
  module_function
16
16
 
17
- # Claude authored — shallow string→symbol key transform; passes non-Hash
17
+ # Shallow string→symbol key transform; passes non-Hash
18
18
  # input through untouched.
19
19
  def symbolize_keys(hash)
20
20
  return hash unless hash.is_a?(Hash)
@@ -3,10 +3,9 @@
3
3
  # =============================================================================
4
4
  #
5
5
  # Single source of truth for the gem version, read by the gemspec and exposed
6
- # at runtime. Pre-1.0 while the gem is proven against AMP before any public
7
- # RubyGems publish.
6
+ # at runtime.
8
7
  # =============================================================================
9
8
 
10
9
  module Equipoise
11
- VERSION = "0.1.0"
10
+ VERSION = "0.2.0"
12
11
  end
data/lib/equipoise.rb CHANGED
@@ -16,8 +16,7 @@
16
16
  #
17
17
  # Equipoise.client.contacts.sync(external_id: user.id, email: user.email, name: user.name, tags: ["AMP"])
18
18
  #
19
- # Contract: documentation/integrations/EXTERNAL_CRM_SYNC_API.openapi.yaml
20
- # Guide: documentation/integrations/EXTERNAL_CRM_SYNC.md
19
+ # API contract and integration guide: https://app.equipoi.se
21
20
  # =============================================================================
22
21
 
23
22
  require "json"
@@ -40,7 +39,7 @@ require "equipoise/custom_fields"
40
39
 
41
40
  module Equipoise
42
41
  class << self
43
- # Claude (External CRM Sync, S12): the process-wide configuration. Built
42
+ # The process-wide configuration. Built
44
43
  # lazily from ENV so a bare `require "equipoise"` is side-effect-free.
45
44
  def configuration
46
45
  @configuration ||= Configuration.new
@@ -52,7 +51,7 @@ module Equipoise
52
51
  configuration
53
52
  end
54
53
 
55
- # Claude authored — memoized default client. Most callers use this; tests
54
+ # Memoized default client. Most callers use this; tests
56
55
  # and multi-tenant producers build their own Client with an explicit config.
57
56
  def client
58
57
  @client ||= Client.new(configuration)
@@ -62,7 +61,7 @@ module Equipoise
62
61
  !configuration.api_key.to_s.empty?
63
62
  end
64
63
 
65
- # — Claude authored (#5) — test-mode kill switch. Put `Equipoise.disable!` in
64
+ # Test-mode kill switch. Put `Equipoise.disable!` in
66
65
  # a producer's rails_helper (or set test env) so no spec can make a live call
67
66
  # even if EQUIPOISE_API_KEY leaks into the environment. Calls become no-ops
68
67
  # returning a benign Response.
@@ -78,7 +77,7 @@ module Equipoise
78
77
  configuration.disabled?
79
78
  end
80
79
 
81
- # Claude authored — reset global state (used by the test suite's before
80
+ # Reset global state (used by the test suite's before
82
81
  # hook; also handy in a console).
83
82
  def reset!
84
83
  @configuration = nil
@@ -6,7 +6,7 @@
6
6
  #
7
7
  # Generated by `rails g equipoise:install`. Reads credentials from the
8
8
  # environment so secrets stay out of source control and key rotation needs no
9
- # redeploy. See documentation/integrations/EXTERNAL_CRM_SYNC.md.
9
+ # redeploy. See https://app.equipoi.se for the API guide.
10
10
 
11
11
  Equipoise.configure do |config|
12
12
  # api_key and base_url are read from EQUIPOISE_API_KEY / EQUIPOISE_API_URL
@@ -17,6 +17,14 @@ Equipoise.configure do |config|
17
17
 
18
18
  # config.base_url = "https://app.equipoi.se/api/v1" # override only if needed
19
19
  # config.logger = Rails.logger # logs retries + failures
20
- # config.max_retries = 2
20
+ #
21
+ # Transport knobs — tunable, but clamped to hard ranges so the gem stays a good
22
+ # citizen to the receiver no matter what you set (out-of-range → clamped + logged):
23
+ # config.read_timeout = 30 # seconds per request; clamped to 5..120. Raise
24
+ # # it further for large batch_sync backfills so
25
+ # # a slow batch never times out and gets re-sent.
26
+ # config.max_retries = 2 # retries on transient failures; clamped to 0..5
27
+ # config.batch_size = 500 # contacts per batch_sync request; clamped to 1..500
28
+ #
21
29
  # config.allow_insecure_http = true # trusted internal HTTP endpoint
22
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: equipoise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Equipoise
@@ -84,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
84
  - !ruby/object:Gem::Version
85
85
  version: '0'
86
86
  requirements: []
87
- rubygems_version: 4.0.10
87
+ rubygems_version: 3.6.9
88
88
  specification_version: 4
89
89
  summary: Ruby client for the Equipoise External CRM Sync API.
90
90
  test_files: []