Draw a sequence

Show one request in order: who calls whom, what comes back, the branches, loops and parallel work, and where it is turned away.

A sequence diagram shows one request in order: who calls whom, what comes back, and where the request is turned away. An architecture diagram shows what a system is made of. A sequence shows the steps of one conversation through it, from top to bottom, as time runs.

The browser posts the login to the API, which finds the user in Postgres; with the right password the API returns a session, and otherwise refuses with a 401. Sign in: 1. Browser calls API: POST /login. Check the password: 2. API calls Users: find user. 3. Users replies to API: user. If password matches: 4a. API replies to Browser: session. Otherwise: 4b. API replies to Browser: 401, refused.The browser posts the login to the API, which finds the user in Postgres; with the right password the API returns a session, and otherwise refuses with a 401. Sign in: 1. Browser calls API: POST /login. Check the password: 2. API calls Users: find user. 3. Users replies to API: user. If password matches: 4a. API replies to Browser: session. Otherwise: 4b. API replies to Browser: 401, refused.

With your agent#

Ask for the steps of one request, in your own words. The agent picks the sequence, follows the code from the route that receives the request to the response, and names the line behind each message.

Draw the sequence of a sign-in with archgram, from the login form to the session.

One sequence is one scenario. For two, a sign-in and a sign-up, ask for two diagrams.

By hand#

diagram: sequence makes a spec a sequence. It lists the participants, then the messages in the order they happen.

yaml
archgram: 1
diagram: sequence
title: Sign in
description: >-
  The browser posts the login to the API, which finds the user in Postgres;
  with the right password the API returns a session, and otherwise refuses
  with a 401.
participants:
  - { id: browser, kind: browser, label: Browser }
  - { id: api, kind: service, label: API, tech: nodedotjs }
  - { id: db, kind: database, label: Users, tech: postgresql }
messages:
  - phase: Sign in
  - { from: browser, to: api, label: POST /login }
  - phase: Check the password
  - { from: api, to: db, label: find user }
  - { reply: db, label: user }
  - alt:
      - when: password matches
        messages:
          - { reply: api, label: session }
      - when: else
        messages:
          - { reply: api, label: "401", refused: true }

Check it and draw it as any spec. The drawing above is this spec.

npm exec -- archgram check docs/diagrams/sign-in.archgram.yaml
docs/diagrams/sign-in.archgram.yaml: valid (a sequence, 3 participants, 5 messages)
npm exec -- archgram build docs/diagrams/sign-in.archgram.yaml
wrote docs/diagrams/sign-in.svg (648 × 505 px, top to bottom)

Participants#

A participant takes a node's fields, id, kind, label, note, tech, variant and source, with the same values. They stand left to right in the order you list them, so list the caller first and each part where the request first reaches it.

Messages#

MessageIn the specDrawn as
A call that waits for its result{ from: api, to: db, label: find user }A solid line with a filled arrowhead
A send that nothing waits for{ from: api, to: queue, label: enqueue, async: true }A solid line with an open arrowhead
A reply{ reply: db, label: user }A dashed line with an open arrowhead
A step inside one part{ from: api, to: api, label: hash password }A loop back to its own lifeline

A reply goes back to the latest call to its sender still waiting. archgram checks that one is, and says where it is not. Here the login is sent with async: true, so nothing waits for the session.

yaml
messages:
  - { from: browser, to: api, label: POST /login, async: true }
  - { reply: api, label: session }
docs/diagrams/sign-in.archgram.yaml:10:14: `api` replies, but no call to `api` is waiting for a reply before it
1 problem in docs/diagrams/sign-in.archgram.yaml

Branches, loops and parallel work#

A fragment holds messages of its own and frames them in the drawing, its operator and first guard in a pill on its edge. Fragments nest.

FragmentHoldsMeans
altTwo ways or more, each with when and messages, the last when: elseOne of them happens, the first whose guard holds
optOne way, when optionalIt happens, or nothing does
loopOne way, when optionalIt is repeated
parTwo ways or more, each with messagesThey happen together, in any interleaving, each in its own order

Each message is numbered by its order. The ways of an alt are alternatives, so their messages carry a letter: 4a for the first way, 4b for the next, each way starting again from the same number.

Phases#

phase names a step of the story, as an item of the top-level messages. The messages after it, up to the next phase, are that phase, drawn as a band across the page with its name. The drawing plays one phase at a time, so the phases are how a reader follows the story. A phase never sits inside a fragment.

A request turned away#

refused: true marks the message that turns the request away, usually a reply such as a 401. A ✕ marks its line at the participant that refuses, in red.

Two looks#

look picks how the parts are drawn. Both draw the same columns, rows and order.

lookHeadsWhile a part answers a callFragments
cards, the defaultarchgram's cardsA thin bar on its lifelineA solid frame, its pill at the left
avatarsCircles, the logo in a badge on the edgeNothingA dashed frame, its pill in the middle
The web app sends the user to the identity provider, which asks for consent and returns a code; the app checks its state, trades the code for a token while it warms the profile cache, then reads the profile page by page, signing in again when the token has expired. Ask for consent: 1. User calls Web app: Sign in. 2. Web app calls Identity provider: redirect to /authorize with the client id and scopes. 3. Identity provider calls User: ask for consent. 4. User replies to Identity provider: consent. 5. Identity provider replies to Web app: code. Trade the code: 6. Web app calls Web app: verify state. In parallel: 7. Web app calls Identity provider: exchange code. 8. Identity provider replies to Web app: token. And: 9. Web app sends to Profile API: warm cache. Read the profile: Repeated, for each page of the profile: 10. Web app calls Profile API: GET /me. If token valid: 11a. Profile API replies to Web app: profile. Otherwise: 11b. Profile API replies to Web app: 401, refused.The web app sends the user to the identity provider, which asks for consent and returns a code; the app checks its state, trades the code for a token while it warms the profile cache, then reads the profile page by page, signing in again when the token has expired. Ask for consent: 1. User calls Web app: Sign in. 2. Web app calls Identity provider: redirect to /authorize with the client id and scopes. 3. Identity provider calls User: ask for consent. 4. User replies to Identity provider: consent. 5. Identity provider replies to Web app: code. Trade the code: 6. Web app calls Web app: verify state. In parallel: 7. Web app calls Identity provider: exchange code. 8. Identity provider replies to Web app: token. And: 9. Web app sends to Profile API: warm cache. Read the profile: Repeated, for each page of the profile: 10. Web app calls Profile API: GET /me. If token valid: 11a. Profile API replies to Web app: profile. Otherwise: 11b. Profile API replies to Web app: 401, refused.

This one is look: avatars. Its spec is in the Examples.

How it moves#

The messages play one phase at a time. The phase that plays has its name darkened, and the other phases' messages dim. Each message's line is drawn from its sender, its arrowhead lit as the line arrives. An alt plays its ways one after another, an "or" by the next way's pill. A par's ways start together, and an opt and a loop play once.

A reader who turns motion off sees the still drawing, every message numbered. A screen reader hears each phase's name and each message in words, in order.

Keep it true#

A participant can name the file behind it, and a message the file with a few words from the line that sends it, as nodes and edges do. archgram check then tells you when that code is gone. Keep a diagram true shows how.

yaml
participants:
  - { id: api, kind: service, label: API, source: ../../src/api.ts }
messages:
  - { from: browser, to: api, label: POST /login, source: '../../src/api.ts#app.post("/login"' }

Every field a sequence may hold is in the Spec format.