Skip to content

Use Case Document

System: Intern Integration Platform (IIP) Related docs: Architecture · Data Model · Implementation Plan

Use cases here cover the full platform, including everything staged for later releases (lifecycle events, target registry, DLQ replay, dashboards). Each use case is tagged with the release it belongs to so the backlog in the Implementation Plan traces directly back to a use case.


1. Actors

ActorKindDescription
HR StaffHuman, primaryEnters and reviews intern records via the Web UI.
Platform OperatorHuman, primaryOperates and maintains the middleware: monitors health, manages the DLQ, configures targets.
Downstream Target SystemSystem, secondaryPostgreSQL, the payroll CSV feed, and any future target — receives fan-out from adapters.
Kafka BrokerSystem, supportingDurable transport; not a "user" but modeled where its behavior (ordering, redelivery) drives a use case.
New Adapter DeveloperHuman, secondaryEngineer extending the platform with a new target adapter. This is a solo project, so Adapter Developer, Platform Operator, and (for demo purposes) HR Staff are all hats worn by the same one person — the actors are separated here by role, not by headcount.

2. Use Case Diagram


3. Use Case Summary

IDNamePrimary ActorRelease
UC-1Submit Intern RecordHR Staff1
UC-2View Intern RecordsHR Staff1
UC-3Edit Intern RecordHR Staff5
UC-4Delete Intern RecordHR Staff5
UC-5Fan-out to Database TargetSystem (Database Adapter)1
UC-6Fan-out to File TargetSystem (File Adapter)1
UC-7Recover from Transient Target FailureSystem1
UC-8Quarantine Poison MessageSystem1
UC-9Add a New Target AdapterAdapter Developer6
UC-10Monitor System Health & Consumer LagPlatform Operator1 (basic) / 4 (dashboards)
UC-11Review and Replay DLQ MessagesPlatform Operator7
UC-12Configure Active TargetsPlatform Operator6

4. Detailed Use Cases

UC-1 — Submit Intern Record

FieldDetail
ActorHR Staff
GoalGet a new intern's data reliably distributed to every downstream target with a single submission.
PreconditionsUI is reachable; Source Service is running; intern.created topic exists.
TriggerHR Staff fills out and submits the intern form.

Main flow:

  1. HR Staff enters intern details in the UI and submits.
  2. UI performs client-side validation and sends POST /interns.
  3. Source Service validates the request server-side (Bean Validation).
  4. Source Service generates recordId (UUID) and createdAt.
  5. Source Service builds the canonical record and validates it against the Schema Registry (Release 3+ — Release 1 builds the canonical record directly via CanonicalMapper, with no registry step yet).
  6. Source Service publishes to intern.created, keyed by internId.
  7. Source Service returns 202 Accepted with the recordId.
  8. UI displays a submission confirmation to HR Staff.

Alternate flows:

  • 3a. Validation fails: Source Service returns 400 Bad Request with field-level errors; UI displays them inline; no event is published.
  • 5a. Canonical record fails schema validation: treated as a server-side bug (should be unreachable if the mapper is correct); logged as a critical error; 500 returned; no event published. (This is a defensive path — the mapper is the thing under test, not the schema.)
  • 6a. Kafka unavailable: publish fails; Source Service returns 503 Service Unavailable; UI shows a retry-able error. No partial state — the record is either fully accepted (published) or fully rejected.

Postconditions: Exactly one canonical event exists on intern.created for this submission, or none exists at all (never a partial publish).

Related NFRs: at-least-once delivery, ordering by internId, contract enforcement.


UC-2 — View Intern Records

FieldDetail
ActorHR Staff
GoalSee previously submitted intern records and their submission status.
PreconditionsAt least the Source Service's read path is available.

Main flow:

  1. HR Staff navigates to the records view.
  2. UI calls GET /interns.
  3. Source Service returns the list of submitted records (from its own read model / query store — not by reading adapter targets, preserving loose coupling).
  4. UI renders the list.

Postconditions: none (read-only). Related NFRs: loose coupling — the UI never queries PostgreSQL or the CSV file directly.


UC-3 — Edit Intern Record (Release 5)

FieldDetail
ActorHR Staff
GoalCorrect or update details of an already-submitted intern.
PreconditionsThe intern record already exists (has a prior intern.created event).

Main flow:

  1. HR Staff opens an existing record in the UI and edits fields.
  2. UI sends PUT /interns/{internId}.
  3. Source Service validates and builds a canonical update record (new recordId, same internId, updatedAt).
  4. Source Service publishes to intern.updated, keyed by internId (same key as the original create, guaranteeing ordering).
  5. Database Adapter applies ON CONFLICT (intern_id) DO UPDATE.
  6. File Adapter rebuilds the CSV snapshot for that internId (see Architecture §7 / Data Model §4) rather than appending.

Alternate flows:

  • 1a. Record doesn't exist: UI/Source Service returns 404.

Postconditions: Downstream targets reflect the updated values; the CSV file has no duplicate/stale line for this intern.

Related NFRs: ordering-by-key (update must be processed after the create it modifies), idempotency (a redelivered update must not double-apply).


UC-4 — Delete Intern Record (Release 5)

FieldDetail
ActorHR Staff
GoalRemove an intern record from all downstream targets (e.g., offboarding).

Main flow:

  1. HR Staff triggers delete in the UI.
  2. UI sends DELETE /interns/{internId}.
  3. Source Service publishes a tombstone-style event to intern.deleted, keyed by internId.
  4. Database Adapter deletes (or soft-deletes, per retention policy) the row.
  5. File Adapter rebuilds the CSV snapshot, omitting the intern.
  6. Every step logged with recordId/traceId for audit purposes.

Postconditions: The intern no longer appears in any downstream target; an audit trail of the deletion exists in logs (and optionally an audit table).

Related NFRs: audit logging, ordering-by-key (a delete must never be processed before its create).


UC-5 — Fan-out to Database Target

FieldDetail
ActorDatabase Adapter (system)
GoalPersist every canonical intern event to PostgreSQL exactly-once in effect, despite at-least-once delivery.
TriggerNew message available on intern.created (or .updated/.deleted in Release 5) for the db-adapter consumer group.

Main flow:

  1. Adapter consumes the message.
  2. Adapter deserializes and validates against the Schema Registry.
  3. Adapter maps canonical record to a SQL row.
  4. Adapter executes INSERT ... ON CONFLICT (record_id) DO NOTHING (or DO UPDATE for update events).
  5. Adapter commits the Kafka offset.

Alternate flows: see UC-7 (transient failure) and UC-8 (poison message).

Postconditions: Exactly one row (or one correctly-updated row) exists per internId, regardless of redelivery count.


UC-6 — Fan-out to File Target

FieldDetail
ActorFile Adapter (system)
GoalAppend every canonical intern event to interns.csv exactly-once in effect.

Main flow:

  1. Adapter consumes the message.
  2. Adapter checks the dedup store: has this recordId already been written?
  3. If not: adapter maps the canonical record to a CSV line and appends it, then records the recordId in the dedup store.
  4. Adapter commits the Kafka offset.

Alternate flows:

  • 2a. recordId already processed: adapter skips the write (no-op) and commits the offset directly — this is the idempotency guarantee, not a failure path.
  • See UC-7 and UC-8 for target/processing failures.

Postconditions: Exactly one CSV line exists per recordId, regardless of redelivery count. No two adapter instances write concurrently (single-writer constraint, see Architecture AD-6).


UC-7 — Recover from Transient Target Failure

FieldDetail
ActorAny adapter (system)
GoalGuarantee no data loss when a target is temporarily unreachable.
TriggerA write to the target throws a classified-retriable error (timeout, connection refused, etc.).

Main flow:

  1. Adapter attempts to write to the target; write fails.
  2. Adapter classifies the failure as retriable.
  3. Adapter does not commit the Kafka offset.
  4. Adapter retries with bounded backoff (e.g., up to 3 attempts).
  5. If a retry succeeds, adapter commits the offset and processing resumes normally.
  6. If all bounded retries fail, the adapter stops consuming that partition and re-attempts on the next poll cycle (the message is never lost — it simply isn't committed) — implementation may either block-and-retry indefinitely at the poll level for infrastructure-down scenarios, or escalate to DLQ after a much larger ceiling, per adapter configuration.

Postconditions: No message is lost; other adapters' consumer groups are unaffected (failure isolation).

Related NFRs: failure isolation, at-least-once delivery.


UC-8 — Quarantine Poison Message

FieldDetail
ActorAny adapter (system)
GoalPrevent one unprocessable message from blocking every message behind it.
TriggerA message fails processing and is classified non-retriable, or a retriable failure exhausts its bounded retry count.

Main flow:

  1. Adapter attempts to process the message; it fails.
  2. Adapter classifies the failure as non-retriable (e.g., schema violation, unmappable data) — or retries are exhausted.
  3. Adapter publishes the original message plus error metadata (error type, stack summary, timestamp, adapter name) to intern.dlq.
  4. Adapter commits the offset on the source topic, unblocking the partition.

Postconditions: The pipeline keeps moving; the bad record is preserved (not lost) in intern.dlq for operator review (UC-11).

Related NFRs: failure isolation, no silent data loss, pipeline liveness.


UC-9 — Add a New Target Adapter (Release 6)

FieldDetail
ActorAdapter Developer
GoalExtend the platform with a new downstream target with zero changes to the UI, Source Service, or existing adapters.

Main flow:

  1. Developer implements a new consumer service following the generic adapter pattern (Architecture §6): consume → deserialize/validate → idempotency gate → transform → write → classify-failure → retry/DLQ.
  2. Developer assigns the adapter its own consumer group.
  3. Developer registers the adapter in the Target Registry (config, not code, in existing services).
  4. Developer deploys the new adapter as an independent service.
  5. Existing services (UI, Source Service, other adapters) require no changes or redeploys.

Postconditions: The new target receives every event published to the relevant topic(s), going forward (and, if desired, replayed from topic retention/DLQ for backfill).

Related NFRs: extensibility-by-addition, independent deployability.


UC-10 — Monitor System Health & Consumer Lag

FieldDetail
ActorPlatform Operator
GoalKnow at a glance whether the platform is healthy and whether any consumer is falling behind.

Main flow (Release 1 — baseline):

  1. Operator queries each service's Actuator /health and /metrics.
  2. Operator opens Kafka UI to inspect consumer group lag per adapter.

Main flow (Release 4 — dashboards):

  1. Operator opens the Grafana dashboard.
  2. Dashboard shows lag per consumer group, DLQ depth, throughput, and per-adapter success/failure counts, sourced from Prometheus scraping each service's Actuator metrics endpoint.

Postconditions: Operator can identify a stuck or lagging adapter before it becomes a user-visible incident.


UC-11 — Review and Replay DLQ Messages (Release 7)

FieldDetail
ActorPlatform Operator
GoalInspect quarantined messages, fix the root cause, and safely reprocess them.

Main flow:

  1. Operator opens the admin dashboard's DLQ view.
  2. Dashboard lists DLQ messages grouped by error type/adapter, non-destructively read from intern.dlq.
  3. Operator diagnoses and fixes the root cause (code fix or data correction).
  4. Operator selects one or more messages and triggers replay.
  5. Replay tool re-publishes the original canonical record to the source topic (intern.created/.updated/.deleted as appropriate).
  6. Replay tool marks the DLQ entry as replayed (audit trail — not deleted, to preserve history).
  7. Normal fan-out and idempotency guarantees apply to the replayed message exactly as to any other.

Postconditions: Previously-quarantined data successfully reaches its targets; an audit trail records what was replayed, when, and by whom.


UC-12 — Configure Active Targets (Release 6)

FieldDetail
ActorPlatform Operator
GoalEnable/disable which adapters are active without redeploying the core platform.

Main flow:

  1. Operator edits the Target Registry configuration (e.g., which adapters are enabled, their connection settings).
  2. Adapters read their enabled/disabled state from the registry at startup (and optionally on a refresh interval).
  3. A disabled adapter's consumer group does not consume — messages accumulate on the topic per retention policy and are available if the adapter is re-enabled later.

Postconditions: The set of active downstream targets is controlled by configuration, not by code changes or redeployments of the core platform.


5. Sequence Diagram — UC-9 in Context (New Adapter Joins a Running System)

This diagram is the visual proof of the extensibility-by-addition principle: nothing about EXIST changes when NEW joins.