Skip to content

record_push_retry re-lowercases a static service name (heap allocation) on every retry attempt, on the provider-storm hot path #329

Description

@erskingardner

Summary

All three retry arms in retry.rs call metrics.record_push_retry(service_name.to_lowercase().as_str()). service_name is always a compile-time-constant &str ("APNs" or "FCM"), so to_lowercase() heap-allocates a fresh String on every retry attempt purely to lowercase a known-at-compile-time label. This runs precisely during provider 429/5xx storms and transport connect-error bursts — exactly the moments the retry path should stay allocation-light.

Location

  • src/push/retry.rs:207 (auth-rejection retry)
  • src/push/retry.rs:231 (transient 429/5xx retry)
  • src/push/retry.rs:409 (transport connect-retry)

Callers always pass a static string: with_retry(..., "APNs", ...) (apns.rs:387), with_retry(..., "FCM", ...) (fcm.rs:560), with_transport_retry(..., "APNs", ...) (apns.rs:600), etc.

Details

Every other push metric already routes through platform_label(platform) (dispatcher/mod.rs:72), which returns the static lowercase "apns"/"fcm" with no allocation. Only the retry path re-derives the lowercase form per attempt via to_lowercase().

Recommendation

Pass the already-lowercase static label ("apns"/"fcm") into with_retry / with_transport_retry instead of the mixed-case "APNs"/"FCM", and drop the per-attempt to_lowercase(). (The mixed-case value is still used for the human-readable warn!(service = service_name, ...) log lines, so keep that or pass both.)

Why this is not a duplicate

#316 is about the metric label semantics (transport connect-retries and provider 429/5xx retries sharing one push_retry_total label). This is strictly the per-attempt allocation, an orthogonal concern.

Impact

Minor allocation churn confined to the retry path. LOW.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions