fix(history): keep unanswered legs so grouped calls stay complete - #356
tommaso-ascani wants to merge 6 commits into
Conversation
The history queries dropped every "NO ANSWER" row that shared its uniqueid with an ANSWERED one, and kept at most one unanswered row per uniqueid+linkedid. That hid the legs a call actually rang: a ring group dials all its members from the SAME channel, so all its legs share one uniqueid and all but one were discarded here. With call grouping those legs are the call's interactions — the middleware collapses them by linkedid into a single expandable row — so they must reach it intact. Removed from both the personal and the switchboard query. Reference NethServer/dev#8105 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bf39022d94
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Code reviewFound 2 issues:
|
Correction to the review aboveI measured issue 1 instead of reasoning about it, and it does not hold as written. Row counts over 60 days on the test PBX, before and after this change:
The two conditions only ever filtered The repetition its list already shows is pre-existing and unrelated: extension 201 gets 46 rows for 26 distinct calls now, and got 45 rows for the same 26 calls before. Those are multiple Issue 2 (the direction filters still dropping legs, so the same call is expandable with no filter and not with "Incoming") stands as written. |
Dropping the leg-deduplication conditions outright changed the response for every consumer of these two endpoints, not only the call history: NethLink lists the same rows in its last-calls panel, and so do the CTI drawers and the mobile app. On this test PBX those callers gained between zero and three rows over two months, all of them queue bookkeeping legs of a single call (three near-identical "401 no answer" entries for one queue call), and the ratio grows with queue size. The conditions are back on by default and skipped only when the caller sets expandLegs, mirroring how removeLostCalls is already plumbed through req.params -> obj -> data. Only the middleware sets it, because it is the only caller that collapses the legs back into one row per linkedid. Reference NethServer/dev#8105 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Only the "all directions" branch let a caller ask for a call's legs, so the same call was expandable with no direction filter and not expandable with "Incoming" or "Internal": those branches hide the unanswered legs of a call that someone did answer, which for a queue or a ring group are the very legs the caller asked to expand. The "lost" branches keep the condition unconditionally: there it is not a deduplication but the definition of the filter, since a lost call is one nobody answered. Reference NethServer/dev#8105 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Issue 2 addressed in eea11a1: the incoming and internal branches now honour The two Issue 1 was already withdrawn above and is now moot: f74ba98 restored the deduplication by default, so every consumer other than the middleware receives exactly what it received before this PR. |
With a direction filter a grouped call had nothing to expand. Every clause in these queries matches leg by leg, and a direction filter keeps only the leg that carries the trunk (switchboard) or the user's own extension (personal view): a queue call's member legs run over Local/<ext>@from-queue channels and never matched, so of the nine legs of one real queue call the incoming filter returned four, and pruning the queue bookkeeping left a single row. Under expandLegs the filter is now applied by linkedid, so any leg matching brings back the whole call. Measured over 60 days on a test PBX: 61 -> 122 rows, and faster than before (0.004s vs 0.018s) since linkedid is indexed. This also means a call the user took part in brings back the legs of the colleagues involved — who else the queue rang, who answered instead — which is what expanding a call is for. It applies only to callers passing expandLegs. Reference NethServer/dev#8105 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Follow-up on issue 2: making those clauses conditional was not enough, and I had picked the wrong clause. A grouped call still would not expand under any direction filter, for a different reason — the filters match leg by leg. The switchboard incoming branch selects rows whose Fixed in 58c70c7: under Worth a second opinion on one consequence: in the personal view a call the user took part in now brings back the legs of the colleagues involved (who else the queue rang, who answered instead). That is what expanding a call is for and what NethServer/dev#7360 asks for, but it is a visibility change, and it is gated behind |
Selecting whole calls by linkedid was applied to both history queries. On the personal view that returned the legs between the user's colleagues too — for one queue call, 7 legs instead of 2 — which is the detail the switchboard view exists for, and which that endpoint gates behind the "switchboard cdr" authorization the personal one does not require. The personal query goes back to matching the legs the user is a party to, as it does on the release branch. The switchboard query keeps selecting whole calls, so a filtered call still expands there. Reference NethServer/dev#8105 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…'s legs A ring group dials all its members from the same channel, so their CDR rows share one uniqueid and the ones that ended the same way were aggregated into a single row before the caller ever saw them: the ringing members were lost, and the non-aggregated columns of the survivor came from an arbitrary leg. Grouping also by the destination channel — the member that was rung — keeps one row per leg, and only for a caller that asked to expand them. Reference NethServer/dev#8105 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reference NethServer/dev#8105
The history queries dropped every
NO ANSWERrow that shared itsuniqueidwith anANSWEREDone, and kept at most one unanswered row peruniqueid+linkedid.That hid the legs a call actually rang. A ring group dials all of its members from the same channel, so every leg shares one
uniqueidand all but one were discarded here — which is why a ring-group call could never be expanded in the call history, while a queue call (whose attempts get their ownuniqueid) could.With call grouping those legs are the call's interactions: the middleware collapses them by
linkedidinto a single expandable row, so they have to reach it intact. Removed from both the personal and the switchboard query.The extra rows are not shown as-is: the middleware groups them, and prunes the queue's own per-member bookkeeping legs (nethesis/nethcti-middleware#70).
Test Case