Skip to main content

Audience Processing (Create/Edit/Delete/Mookept)

Overview

An audience is the target group used for multicast campaign delivery. The CMS side only records the request in the database and pushes a job onto a queue — all of the heavy lifting happens in this worker: reading LINE User IDs from the uploaded file, validating their format, fetching profiles from LINE and upserting them into line_user, generating a summary CSV, and writing the resulting statistics back to the audience table.

Four separate queues handle the four commands: create, update, delete, and mookept (bulk add or remove of members).

Business Flow

Create Audience (create_audience)

  1. Receive an AudienceQueueType payload containing audienceId, lineOaId, organizationId, and the uploaded file path.
  2. processValidationPayload loads the audience row along with the associated OA data — lineOaHash, access token, and login channel.
  3. Read the uploaded file from S3 and split it into a list of LINE User IDs.
  4. Filter the list with the regular expression ^U[a-f0-9]{32}$ via isValidLineUserID, discarding malformed entries and duplicates.
  5. For each valid ID, fetch the profile from LINE with GetProfile and find-or-create the line_user row — creating it if it does not exist, or refreshing the display name, picture, and language if it does.
  6. Generate a single-column CSV with the header Line UserID, named audience-<id>-<timestamp>.csv, and upload it to S3 under private/<lineOaHash>/audience/.
  7. Merge the statistics (total, valid, invalid) and the new file path into the audience.info jsonb column.
  8. Call the trigger evaluator to evaluate audience_membership rules for the members who were added or removed.

Update Audience (update_audience)

Follows the same flow as create, with one addition: the old and new member lists are diffed to determine who was added and who was removed, and both sets are passed to the trigger evaluator.

Delete Audience (delete_audience)

Clears all memberships by removing the audience id from line_user.audience_ids, then marks the audience row as deleted.

Mookept (mookept_audience)

The payload carries an actionType field that selects the direction: add invokes AppendMembersByAudienceID, anything else invokes RemoveMembersByAudienceID. Both methods handle their own errors internally — they log and return — so the handler always acks, matching the behaviour of the legacy system.

Key Files & Functions

  • internal/audience/consumer.goConsumer.Register() binds handlers to all four queues: OnAudienceCreateProcess, OnAudienceUpdateProcess, OnAudienceDeleteProcess, and OnMookeptAudienceUpdateProcess.
  • internal/audience/service.go — the domain's core logic
    • CreateAudience(), UpdateAudience(), DeleteAudience()
    • AppendMembersByAudienceID(), RemoveMembersByAudienceID()
    • processCreateFileData(), processUpsertLineUserByLineUserID(), processValidationPayload()
    • mergeStatsIntoInfo(), diff(), isValidLineUserID()
  • internal/audience/interfaces.go — narrow interfaces that keep responsibilities separated: CSVReader, Storage, LineOaLookup, LineProfileFetcher, LineUserUpserter, and AudienceTriggerEvaluator.
  • internal/audience/repository.go and internal/audience/payloads.go
  • cmd/worker/integration.go — the concrete adapters behind those interfaces: audienceStorage, lineOaForAudience, lineProfileForAudience, lineUserRepo, and audienceTriggerAdapter.
  • Queues: create_audience, update_audience, delete_audience, and mookept_audience (runtime profile main).

Connections to Other Services

  • Job source — cms-api-go (audience domain) enqueues work whenever a user creates, edits, or deletes a target group.
  • Databaseaudience (the info jsonb column), line_user (upsert plus audience_ids), and line_oa.
  • S3 — reads the uploaded source file and writes the result CSV to private/<lineOaHash>/audience/.
  • LINE APIGET /v2/bot/profile/{userId} for profile lookups.
  • Trigger engine — calls EvaluateAudienceTriggers on every membership change.
  • Downstream consumer of the CSV — the file produced here is exactly what the multicast campaign delivery job reads at send time.