Skip to content

refactor: simplify push and logging hot paths#874

Open
appleboy wants to merge 2 commits into
masterfrom
refactor/simplify-cleanup
Open

refactor: simplify push and logging hot paths#874
appleboy wants to merge 2 commits into
masterfrom
refactor/simplify-cleanup

Conversation

@appleboy

@appleboy appleboy commented Jun 6, 2026

Copy link
Copy Markdown
Owner

Summary

Behavior-preserving cleanup of the push and logging code surfaced by a /simplify review across the codebase. Removes duplication (a shared retry-clamp helper, merged HTTP/HTTPS startup), trims wasted work on the per-token hot path (log output built only when the level is enabled, iOS stat counters batched into one update, slices preallocated), and collapses redundant code. No external behavior or public API changes.

Architecture / flow

The only runtime-shape change worth a picture is the iOS push loop in notify/notification_apns.go: per-token goroutines previously hit stat storage once per token; they now accumulate into atomic counters and flush once after the wait barrier (identical totals, far fewer stat-storage round-trips on the Redis backend).

flowchart TD
    Start[PushToIOS batch] --> Spawn[spawn goroutine per token]
    Spawn --> Push[client.PushWithContext]
    Push --> Ok{sent ok?}
    Ok -- yes --> Sinc[successCount.Add 1]
    Ok -- no --> Einc[errorCount.Add 1 + append retry token]
    Sinc --> Wait[wg.Wait barrier]
    Einc --> Wait
    Wait --> Flush[single AddIosSuccess / AddIosError flush]
    Flush --> Retry{retryable tokens left?}
    Retry -- yes --> Start
    Retry -- no --> Done[return resp]

    style Sinc fill:#dff0d8,stroke:#3c763d
    style Einc fill:#dff0d8,stroke:#3c763d
    style Flush fill:#dff0d8,stroke:#3c763d
Loading

AI Authorship

  • AI was used. Details:
    • Tool / model: Claude Code (Opus 4.8), via the /simplify workflow
    • AI-authored files: all 11 changed files
    • Human line-by-line reviewed: all 11 files reviewed line-by-line by the author before opening this PR

Change classification

  • Core code (broad impact — needs line-by-line review)

Touches the shared push path (notify/) and logging (logx/). The changes are behavior-preserving, but these modules are central, so the stricter review bar applies.

Plan reference

No plan doc — this is a follow-up cleanup from a /simplify review. Goal: reduce duplication and wasted work without changing behavior.

Verification

  • Existing unit/integration tests pass locally (go test -tags sqlite ./...)
  • New tests added — N/A, no behavior change; existing coverage exercises the touched paths
  • Note: 4 notify/router tests fail in this environment with missing fcm credential data; confirmed pre-existing (they fail identically on the unchanged base tree — they require FCM_CREDENTIAL/FCM_TEST_TOKEN)
  • Manual verification run:
    • go build -tags sqlite ./... — success
    • go vet -tags sqlite ./... — no issues
    • gofmt -l on changed dirs — clean

Verifiability check

  • Each change maps to a named refactor (retry clamp, server startup merge, log gating, stat batching, slice prealloc, header parsing, dead-code removal)
  • Reviewer can confirm correctness from signatures + the unchanged call sites; counter totals are provably identical (one Add per outcome → same sum)

Risk & rollback

  • Risk: Low. The highest-touch change is the iOS stat-counter batching in concurrent code — totals are unchanged, only the number of stat-storage writes drops. Log-level gating skips building strings that were previously built-then-discarded.
  • Rollback: Revert the single commit on this branch; nothing depends on the new internal helpers.

Reviewer guide

  • Read carefully:
    • notify/notification_apns.go — atomic counters + post-wg.Wait() flush (concurrency)
    • logx/log.goLogPush split into formatPushLog, gated on IsLevelEnabled (confirm output identical for json + text, succeeded + failed)
  • Spot-check OK:
    • effectiveMaxRetry helper + its three call sites
    • router/server_normal.go merged startup helper
    • notify/feedback.go strings.Cut, rpc/server.go no-op removal, notify/global.go constant removal, app/sender.go return err collapse, slice preallocations

🤖 Generated with Claude Code

appleboy and others added 2 commits June 6, 2026 17:07
- Extract a shared retry-clamp helper for the iOS, Android, and Huawei push functions
- Merge the duplicate HTTP and HTTPS server startup helpers into one
- Build push log output only when the destination log level is enabled
- Batch per-token iOS success and error counters into a single stat update
- Preallocate FCM message and failure log slices to their known size
- Parse feedback headers with strings.Cut so values containing a colon are kept
- Drop a no-op topic reassignment and an unused misspelled priority constant
- Collapse redundant error-return blocks and a verbose topic check
The per-token goroutines in PushToIOS appended to the shared resp.Logs
and newTokens slices without synchronization. With MaxConcurrentPushes
defaulting to 100, many goroutines run in parallel and race on the slice
headers, which can drop log entries, drop retryable tokens, or panic on a
backing-array reallocation. The prior change made the stat counters atomic
but left these two appends unguarded; add a mutex around both.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant