Skip to content

nethvoice-report: CDR partition tables contaminated with cross-period rows #8023

@edospadoni

Description

@edospadoni

Problem

Two distinct issues in nethvoice-report cause incorrect counts and prevent the nightly reports scheduler from completing successfully.

A. CDR partition tables contaminated with cross-period rows

CDR partition tables in asteriskcdrdb (cdr_YYYY and cdr_YYYY-MM) accumulate rows belonging to periods other than the table's own period. This silently inflates counts returned by any API query whose date range spans more than one month, and inflates every CDR dashboard widget by approximately 2x.

Root cause — daily INSERT IGNORE in partition templates

root/opt/nethvoice-report/api/templates/cdr_year.sql and cdr_month.sql contain a daily INSERT IGNORE block that copies "yesterday's" rows from the source cdr table (or year table) into the partition target. The block filters by calldate >= NOW() - INTERVAL 1 DAY AND calldate < NOW() but lacks any constraint on the target table's own period.

The nightly tasks cdr job iterates every year/month from cdr_first_month to the current month, and for every iteration it executes the INSERT IGNORE block. As a result, yesterday's rows are inserted into every historical partition table, regardless of whether yesterday belongs to that partition's period.

Runtime symptom 1 — multi-month API queries

api/methods/queries.go buildCdrQuery builds a UNION ALL across the monthly partition tables that intersect the requested time range. Each subquery applies the same outer WHERE calldate BETWEEN start AND end. When a partition table contains rows belonging to other months that fall inside the requested range, those rows are returned by both their "rightful" partition and any contaminated partition, double-counting.

Example: with date range March–April, the outbound recap summary returns ~5992 calls instead of the correct ~4083 (March 2261 + April 1822).

Runtime symptom 2 — dashboard widgets

The precomputed dashboard tables dashboard_cdr_*_past_* are built by root/opt/nethvoice-report/api/views/dashboard_cdr_*.sql. These views read from year tables (cdr_YYYY) and UNION ALL the previous-year and current-year tables. When either year table contains rows of the other year (the contamination above), every dashboard widget for past_week, past_month, past_quarter, past_semester, past_year, current_* is inflated approximately 2x.

B. tasks views fails with "invalid connection"

The tasks views command in tasks/cmd/views.go runs each view SQL file in parallel (semaphore = 4 goroutines) with multiStatements=true. Most view files are multi-statement (a chain of DROP TABLE IF EXISTS ...; CREATE TABLE ... AS SELECT ...;). db.Query() returns only the first result set; subsequent result sets stay queued on the connection. The current code calls rows.Close() without iterating rows.NextResultSet() first, so the connection is returned to the pool while still holding pending results. When the next goroutine reuses that connection the mysql driver detects the bad state and the query fails with driver.ErrBadConn (surfaced as "invalid connection"), aborting the whole scheduler before views completes.

Combined effect

  • Multi-month API CDR queries (pbx and personal sections) over-count by a factor proportional to the number of months covered.
  • All 18 dashboard CDR widgets inflated by ~2x.
  • Multi-month group-by-month charts show duplicated values on every visible month.
  • The nightly reports-scheduler.service aborts on a random view file with "invalid connection", leaving dashboard_cdr_* and queue-derived precomputed tables not refreshed.

Fix

Metadata

Metadata

Assignees

No one assigned

    Labels

    nethvoiceBug or features releted to the NethVoice project

    Type

    No fields configured for Bug.

    Projects

    Status
    In Progress

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions