Marking a next-response SLA event met or breached never updated
conversations.next_sla_deadline_at, so the conversation kept sorting as if
the reply was still due. Reopening a resolved conversation had the same
problem in reverse: the column stays NULL even though its deadlines are
live again.
A team or policy change between evaluation ticks deleted outcomes the tick had not
stamped yet: an incurred breach vanished and a met first reply got re-judged under the
new policy. ApplySLA now evaluates the outgoing SLA first, apply-sla scores and keeps
overdue next-response events, and the deadline recompute reads only the latest SLA's
events. Also adds fetching/fetched logs around both evaluation loop queries.
Superseded SLAs now get their status from first-response/resolution outcomes, with
next-response events judging only next-response-only policies. Re-applying an SLA no
longer cancels unsent breach escalations, and deadline recomputes now lock the
conversation row so the sweep can't overwrite a fresh deadline with a stale one.
The conversation deadline only ignored the first-response deadline after the tick
stamped first_response_met_at, so a conversation could show an already-satisfied
first-response deadline for up to one 5m tick. Gate it on first_reply_at too, drop
a redundant applied_slas re-join in the sweep, and add tests for both cases.
Profiled the prod alloc with pprof. Three things stood out.
SLA evaluation was refetching about 234k pending rows every 10 minutes and the
count only ever grew. A policy can leave the resolution time blank, which
stores a NULL resolution deadline. The evaluator needs a deadline to compare
against, so it could never set met_at or breached_at, and the row stayed
pending forever. The pending query now skips a metric with no deadline, and a
new set based query closes any pending row whose configured metrics have all
settled. It replaces the old per row status update, so there is one status
writer and the backlog drains itself on the first tick. No migration is needed
because nothing outside the sla package reads that status.
Static assets were copied into fasthttp's pooled per connection response
buffer on every request. That buffer keeps its grown size, so serving the
frontend bundle held about 165MB. SetBodyRaw points at the bytes instead of
copying them.
API key auth ran a full bcrypt compare on every request, which was 62 percent
of cpu samples. API secrets are 64 char random tokens, so bcrypt's work factor
buys nothing there. They are now hashed with sha256 and compared in constant
time. Old bcrypt hashes still verify and get upgraded in place on first use,
so no key needs reissuing. Password login still uses bcrypt.
This also fixes an unrelated bug the work turned up. apply-sla deleted pending
rows by status alone, so re-applying an SLA threw away a first response breach
that was already recorded. It now deletes only rows with nothing recorded and
closes the rest to their terminal status first.
Targets broadcasts via per-tab list and open subs (validated at subscribe time)
instead of broadcasting message uuid to all agents. Adds frontend list typing, throttled sound,
and many perf improvements to reduce cpu memory & database queries.
Other fixes: Enforce message-to-conversation binding in handleGetMessage
- Introduced a new category field for conversation statuses to classify them as 'open', 'waiting', or 'resolved'. Which allows max assignment limits in team to work with custom statuses as well.
More polishes to notif panel
Add `You` for current agent in select combobox.
Remove unncesary checks for existing notifications while marking it as read.
Send oldest SLA notifcation first (update sql query)
- Passes appliedSLAID directly to SLA logic instead of refetching
- Adds appliedSLAID field to conversation struct (already fetched in get-conversation query)
prevents multiple update queries unnecessarily on applied sla table.
clear next sla deadline in conversations properly when there's no deadline to be met.
uses the new status column in the applied sla table to determine if the sla is still active and has to be calculated again.
feat: store user roles in user roles table, drops the roles table on users table.
feat: standardize column names in schema, renames disabled bool to enables.
- vue router fixes to allow components / pages to rerender after creating an object in db.
- minor fixes and refactors.