• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GeorgeSG / KoInsight / 22582769013
56%

Build:
DEFAULT BRANCH: master
Ran 02 Mar 2026 03:27PM UTC
Jobs 1
Files 39
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

02 Mar 2026 03:26PM UTC coverage: 56.065% (+2.3%) from 53.749%
22582769013

push

github

web-flow
Harden sync (#99)

Fix last_open corruption, data loss, and edge case crashes

## Problems

### Main bugs

Several bugs were causing incorrect or missing data after syncing:

- "56 years ago" last open date: the annotation sync path read
summary.modified (an ISO date string like "2024-11-30") as the last_open
timestamp. SQLite coerced it to 0, making every book appear last opened
at Unix epoch (1970)
- Last open date on bulk sync: after fixing the above, os.time() was
used as a fallback — but the sidecar contains no reliable last-open
timestamp at all. This caused every bulk-synced book to be stamped with
the sync time instead of the actual last open date
- Silent data loss on manual sync: KoReader buffers reading session
stats in memory and only flushes to disk every ~50 page turns.
Triggering a sync mid-session meant the current session's data was never
captured. Sync-on-suspend was unaffected because the suspend event chain
flushed to statistics.sqlite3 beforehand

### Captured along the way

- In valid page stats reaching the DB: no server-side validation on
duration or total_pages fields, allowing null/NaN/zero values to be
inserted
- Server error on annotation-only sync: the plugin sends stats = {}
(empty Lua table → JSON object {}) on the annotation-only path (simplest
option is sending one data strucutre server-side). Calling .filter() on
a plain object threw TypeError, returning HTTP 500
- "NaN" avg. daily reading time: possible division by zero on the book
detail page when a book had no recorded reading days yet.
- Infinity started-reading date: getStartedReading() returned Infinity
for books with no page stats, which could propagate to the client

## Solutions

- Plugin: Set last_open = 0 in the annotation sync path. The sidecar
file contains no reliable last-open timestamp, and the statistics sync
path already sets this correctly. The server-side guard skips merging
zero values, so this is safe.
- Plugin: call ReaderStatistics:insertDB() b... (continued)

175 of 308 branches covered (56.82%)

Branch coverage included in aggregate %.

10 of 10 new or added lines in 2 files covered. (100.0%)

412 of 739 relevant lines covered (55.75%)

11.66 hits per line

Jobs
ID Job ID Ran Files Coverage
1 22582769013.1 02 Mar 2026 03:27PM UTC 39
56.06
GitHub Action Run
Source Files on build 22582769013
  • Tree
  • List 39
  • Changed 3
  • Source Changed 2
  • Coverage Changed 3
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #22582769013
  • d5592a3f on github
  • Prev Build on master (#21561280025)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc