Make a failed send the whole message's answer, with no merged report after it #23
@@ -322,9 +322,10 @@ const { err, pduObjs, smsIds, unanswered } = await session.sendSms({ from, messa
|
|||||||
- One id per segment. `smsIds` is positional with `pduObjs`, and an entry is `undefined` where the
|
- One id per segment. `smsIds` is positional with `pduObjs`, and an entry is `undefined` where the
|
||||||
SMSC took the segment without naming an id; some name one for the first segment only. No receipt
|
SMSC took the segment without naming an id; some name one for the first segment only. No receipt
|
||||||
ever carries an empty id, so an unnamed entry matches nothing.
|
ever carries an empty id, so an unnamed entry matches nothing.
|
||||||
- `err` is set when the SMSC refuses a segment, naming the status. Every segment goes out together,
|
- `err` is set when the SMSC refuses a segment, naming the status, or leaves one unanswered. Every
|
||||||
so `pduObjs` and `smsIds` then hold what was accepted: enough to reconcile a later receipt, not
|
segment goes out together, so `pduObjs` and `smsIds` then hold only the accepted segments, in send
|
||||||
enough to resend the rest. Treat a partial failure as a failed message.
|
order: enough to reconcile a later receipt, not enough to resend the rest. Treat a partial failure
|
||||||
|
as a failed message; its accepted segments report through `dlr` alone.
|
||||||
- `unanswered` counts segments that went out and were never answered. The SMSC may have taken each
|
- `unanswered` counts segments that went out and were never answered. The SMSC may have taken each
|
||||||
and lost only the response, so a message with `unanswered` above zero cannot be resent without
|
and lost only the response, so a message with `unanswered` above zero cannot be resent without
|
||||||
risking a duplicate.
|
risking a duplicate.
|
||||||
@@ -480,7 +481,8 @@ carrying the worst status of the segments and each of them under `segments`. An
|
|||||||
report never counts. Merging needs the SMSC to number its segment ids `<base>-<n>`, this library's
|
report never counts. Merging needs the SMSC to number its segment ids `<base>-<n>`, this library's
|
||||||
own server's convention; an SMSC that hands out unrelated ids per segment never fires it. A base is
|
own server's convention; an SMSC that hands out unrelated ids per segment never fires it. A base is
|
||||||
merged once: a later message the SMSC gives the same ids is reported through `dlr` alone, and an
|
merged once: a later message the SMSC gives the same ids is reported through `dlr` alone, and an
|
||||||
earlier one still collecting loses its merged report.
|
earlier one still collecting loses its merged report. A send that returned an `err` never fires `messageDlr`,
|
||||||
|
even where the SMSC took some of its segments; their receipts still arrive as `dlr`.
|
||||||
|
|
||||||
## Server in depth
|
## Server in depth
|
||||||
|
|
||||||
@@ -658,7 +660,8 @@ one wins. They do not override the hard rules below.
|
|||||||
nothing, so nothing the library concludes may rest on one; a request the peer may already have
|
nothing, so nothing the library concludes may rest on one; a request the peer may already have
|
||||||
taken is never re-sent on the library's own initiative; work the peer has no reason to send again
|
taken is never re-sent on the library's own initiative; work the peer has no reason to send again
|
||||||
is not dropped; a call that reports a message as sent asserts that the wire carried what the caller
|
is not dropped; a call that reports a message as sent asserts that the wire carried what the caller
|
||||||
wrote, so a value we cannot send as given is refused before anything goes out.
|
wrote, so a value we cannot send as given is refused before anything goes out; each message gets
|
||||||
|
one outcome as a whole, so a send that fails is that outcome and no merged report follows it.
|
||||||
3. **Strict in what we send, generous in what we read.** The library's own senders follow 3.4, and
|
3. **Strict in what we send, generous in what we read.** The library's own senders follow 3.4, and
|
||||||
the codec parses whatever arrives. Where the letter of the spec would discard traffic a real SMSC
|
the codec parses whatever arrives. Where the letter of the spec would discard traffic a real SMSC
|
||||||
sends, keep the traffic.
|
sends, keep the traffic.
|
||||||
|
|||||||
@@ -202,13 +202,8 @@ and is also what the panel ranked hardest — two methods, one answer.
|
|||||||
`broadcast_sm_resp` is declared, set once and read nowhere. This is the "Dormant filters" row
|
`broadcast_sm_resp` is declared, set once and read nowhere. This is the "Dormant filters" row
|
||||||
of the 0.4.0 defect table in a new spelling — metadata that reads as a guarantee.
|
of the 0.4.0 defect table in a new spelling — metadata that reads as a guarantee.
|
||||||
|
|
||||||
- [ ] **Arm the merge for the segments the SMSC did take, or say why not.** `collectSent()` sets
|
- [ ] **Test that a multipart send which errors never fires `messageDlr`.** Goal 2 now says so and
|
||||||
`failure` if any segment errored, including the `UnansweredError` a mid-send drop produces, and
|
README promises it; `session-extras.test.ts` covers a drop *after* the send, not one during it.
|
||||||
`session.ts` only calls `dlrMerger.expect(sent.smsIds)` when `!sent.err`. So a link drop during
|
|
||||||
a multipart send leaves per-segment `dlr` events firing while `messageDlr` never can, traced
|
|
||||||
only by one `debug` line. `session-extras.test.ts` has the adjacent case — a drop *after* the
|
|
||||||
send — and not this one. If goal 2 forbids reporting on a message we cannot fully account for,
|
|
||||||
that is the answer; it is stated in no file today either way.
|
|
||||||
|
|
||||||
- [ ] **Return an `err` where `message` is not a string, rather than throwing.**
|
- [ ] **Return an `err` where `message` is not a string, rather than throwing.**
|
||||||
`sendSms({ message: undefined })` — a forgotten property — reaches `value.replace()` in
|
`sendSms({ message: undefined })` — a forgotten property — reaches `value.replace()` in
|
||||||
|
|||||||
Reference in New Issue
Block a user