Skip to content

Add APNs Live Activity broadcast channel support - #46

Open
mithileshchellappan wants to merge 2 commits into
mainfrom
feat/apns-live-activity-channels
Open

Add APNs Live Activity broadcast channel support#46
mithileshchellappan wants to merge 2 commits into
mainfrom
feat/apns-live-activity-channels

Conversation

@mithileshchellappan

Copy link
Copy Markdown
Owner

Summary

  • Add database-backed APNs Live Activity broadcast channels
  • Implement channel creation, registration, dispatch, and fanout flows
  • Preserve direct-token delivery compatibility
  • Document the API, migration, setup, and channel behavior

Testing

  • Added and updated Go unit tests across APNs, server, service, storage, and worker flows
  • Validated channel dispatch, fanout, persistence, and partial failure behavior

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — This PR adds database-backed APNs Live Activity broadcast channels while preserving the existing direct-token delivery path.

  • Add APNs channel management and broadcast deliveryClient now creates and deletes no-storage channels, publishes update and end events through Apple’s broadcast endpoint, and supplies channel or update-token inputs for capable remote starts.
  • Persist channel mappings and client capability — Migration 16, PostgresStore, and service logic store activity-to-topic channel mappings, track capable APNs start tokens, reconcile concurrent provisioning, and retire stale channels safely.
  • Integrate mixed-cohort fanout — Live Activity jobs carry matching channel IDs through the existing worker pipelines, count one channel task alongside direct APNs and FCM targets, and isolate channel failures from token invalidation.
  • Expose and document channel workflows — New HTTP routes, OpenAPI schemas, setup guidance, and end-to-end documentation cover provisioning, lookup, deletion, client registration, remote starts, and update delivery.
  • Extend regression coverage — APNs, server, service, storage, and worker tests exercise wire payloads, persistence ambiguity, races, capability propagation, dispatch accounting, and partial failures.

Pullfrog  | View workflow run | Using GPT Sol𝕏

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 679a2a75af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 848 to 849
switch action {
case string(model.LiveActivityActionStart):
if err := s.FailLAJobIfActive(ctx, jobID); err != nil && !errors.Is(err, Errors.NotFound) {
return fmt.Errorf("error failing empty LA start job: %w", err)
}
case string(model.LiveActivityActionEnd):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore failure handling for empty start dispatches

When a start dispatch finds no eligible tokens, CompleteLADispatchEnqueue reaches this switch with a zero total, but the removed start case now leaves the job ACTIVE while marking its only dispatch completed. No device received the start, and later attempts using the same activityId are returned as already_started by CreateOrGetLAStartJob, so registering a token and retrying cannot recover the activity. Continue failing an empty start job rather than leaving an unusable active record.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7bcb9393b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return nil, fmt.Errorf("failed to get JWT: %w", err)
}
endpoint := fmt.Sprintf(
"%s/1/apps/%s/channels",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Address the channel resource in DELETE requests

For every channel deletion, this builds the collection URL /1/apps/{bundle}/channels and supplies the channel ID only as an apns-channel-id header. APNs channel management deletes /1/apps/{bundle}/channels/{channelID}, so DELETE /v1/live-activity/channels/{activityID} receives a provider error and retains the local mapping instead of deleting the channel; append the escaped channel ID to the URL for DELETE requests.

Useful? React with 👍 / 👎.

Comment on lines +263 to +264
if req.TopicID != "" {
channel, _, err := s.ProvisionLAChannel(ctx, req.ActivityID, req.TopicID)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid provisioning a channel for an already-started activity

When the original topic-scoped start continued token-only after channel provisioning failed, retrying the same start after APNs recovers reaches this call before CreateOrGetLAStartJob. EnsureLAChannel sees the matching existing job, creates and stores a new channel, and then the start returns already_started without enqueueing another start containing input-push-channel; consequently no existing activity subscribes to the channel, while later updates send a redundant broadcast to it and the mapping consumes a remote channel until manually deleted.

Useful? React with 👍 / 👎.

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