Flow: Broadcast Campaign
End-to-end sequence for a broadcast campaign from creation to delivery. Services: hbf-console, hbf-core, hbf-broadcast, Facebook/Teams/Slack/Viber/SMTP
Sequence Diagram
Step-by-Step
-
Campaign creation (hbf-console -> hbf-core): A user creates a broadcast campaign in the console, specifying the target audience (subscriber filters), content (message templates per channel), and schedule. The campaign is saved in hbf-core with status
pending. -
Polling (hbf-broadcast -> hbf-core): The hbf-broadcast daemon runs an infinite loop, polling hbf-core every 60 seconds for broadcasts with
status: pendingandsendBeforeless than or equal to the current time. -
Subscriber resolution (hbf-broadcast -> hbf-core): For each pending broadcast, hbf-broadcast fetches the bot deployment configuration (channel credentials) and resolves the subscriber list via SubscribersClient.
-
Message template resolution (hbf-broadcast -> hbf-core): hbf-broadcast fetches or creates message templates via ResponsesClient, resolving any dynamic content or variables.
-
Batched delivery (hbf-broadcast -> channel APIs): Subscribers are grouped by channel. Each batch is sent via the appropriate channel API:
- Facebook:
POST /me/messages(individual) or/me/broadcast_messages(bulk) - Teams:
POST /v3/conversations/{id}/activitiesvia MS Bot Framework - Slack:
POST chat.postMessage - Viber:
POST broadcast_message - Email: nodemailer SMTP transport
- Facebook:
-
Progress tracking (hbf-broadcast -> hbf-core): After each batch, hbf-broadcast updates the broadcast status in hbf-core with
currentBatchandtotalBatchescounts, allowing the console to show progress. -
Completion (hbf-broadcast -> hbf-core): When all batches are sent, hbf-broadcast sets the broadcast status to
complete. If any batch fails irrecoverably, it sets status toerrorwith the error details.
Contracts
hbf-broadcast -> hbf-core (polling):
BroadcastsClient.findAllBy({ status: "pending", sendBefore: Date })
-> Broadcast[]
hbf-broadcast -> hbf-core (status update):
BroadcastsClient.save(broadcastId, {
status: "in_progress" | "complete" | "error",
error: "string" | null,
currentBatch: number,
totalBatches: number
})
hbf-broadcast -> hbf-core (deployment + subscribers):
BotDeploymentClient.findByTenantId(tenantId) -> deployment config
SubscribersClient.findByHandle(handle) -> subscriber
SubscribersClient.create(subscriberData) -> subscriber
ResponsesClient.findAllBy(filters) -> Response[]
ResponsesClient.createOrUpdate(responseData) -> Response
hbf-broadcast -> Facebook:
POST /me/messages
{ "recipient": { "id": "user_id" }, "message": { "text": "..." } }
hbf-broadcast -> Teams:
POST /v3/conversations/{conversationId}/activities
{ "type": "message", "text": "..." }
hbf-broadcast -> Slack:
POST chat.postMessage
{ "channel": "channel_id", "text": "..." }
hbf-broadcast -> Viber:
POST broadcast_message
{ "broadcast_list": ["user_id"], "type": "text", "text": "..." }