Skip to content

refactor: one seconds-interval helper; coverage tracks greenlet switches - #242

Merged
lesnik512 merged 2 commits into
mainfrom
refactor/seconds-interval
Oct 17, 2026
Merged

lesnik512 merged 2 commits into
mainfrom
refactor/seconds-interval

Conversation

@lesnik512

@lesnik512 lesnik512 commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Cosmetic, no issue. The three make_interval(0, 0, 0, 0, 0, 0, :param) calls in client.py now go through one _seconds(name) helper:

  • the fetch's lease cutoff;
  • the INSERT's activate_in;
  • mark_pending_with_lease's retry delay.

Two comments that explained the six zeros and the clock-skew reason are folded into its docstring.

Why not make_interval(secs => ...)

That was the original idea. SQLAlchemy's func has no named-argument form, so it would need a custom compiled element. It would also change the SQL text, which moves the pg_stat_statements query ids the benchmark gate counts. The helper keeps the SQL byte for byte.

Verification

  • The compiled fetch statement and all eight INSERT variants are identical to main's.
  • just bench-check passes, which also covers mark_pending_with_lease.
  • After rebasing onto main, 762 tests pass in docker at 100% coverage, and ruff and ty are clean.

Also in this PR: coverage tracks greenlet switches

This PR's pytest (3.11) job failed twice in a row, though all 744 tests passed both times. The coverage gate reported tests/test_integration.py:1512 as never run. That line is a publish loop in test_batched_flush_dlq_row_stays_inline, and the PR doesn't touch it.

Main has the same flake. I ran that test 15 times under coverage and counted the runs that reported line 1512 missed:

missed
main, 3.11 5 of 15
this branch, 3.11 7 of 15
this branch with concurrency = ["greenlet", "thread"], on 3.11, 3.12 and 3.13 0 of 15 each

Cause: SQLAlchemy's async layer runs every statement in a greenlet. Coverage's C tracer loses its place across a greenlet switch it isn't tracking, so a line that runs after await session.execute(...) can go unrecorded. #235 worked around this with core = "sysmon", but Python 3.11 has no sys.monitoring, so the 3.11 job kept the C tracer and the flake.

The change: [tool.coverage.run] now sets concurrency = ["greenlet", "thread"] and drops core = "sysmon" and its no-sysmon warning filter.

  • sysmon goes away: coverage 7.16 can't combine sysmon with greenlet tracking. It falls back to the C tracer with a no-sysmon warning, and the old filter would have hidden that. Every version now uses the same tracer.
  • Speed: the full suite runs in about the same time, 36 s.
  • Branch coverage: just test-branch misses 16 partial branches against main's 20. The tracer was dropping those 4 too.

@github-actions

github-actions Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Benchmark gate

✅ gate passed

scenario msg/s delete/msg WALrec/msg WALB/msg fpi upd del dead_tup
consumer/w1/b10 1935 1.000 6.71 920 242 5000 5000 10000
consumer/w1/b100 1676 1.000 7.11 1154 243 5000 5000 10000
consumer/w2/b10 2476 1.000 6.72 924 242 5000 5000 10000
consumer/w2/b100 3081 1.000 7.11 1154 243 5000 5000 10000
consumer/w4/b10 2498 1.000 6.73 940 242 5000 5000 10000
consumer/w4/b100 3104 1.000 7.11 1153 243 5000 5000 10000
consumer/w1/b100/tfbs100 9976 0.010 6.11 1130 243 5000 5000 10000
consumer/w1/b100/interval1-10 2030 1.000 7.11 1154 243 5000 5000 10000
producer/w1/b100 5741 0.000 3.04 597 1 0 0 0
producer/w1/b100/ppt1 1738 0.000 4.04 635 0 0 0 0

Gated (fails the build): delete_calls + tuple counters (upd/del/ins) + the producer's insert_calls, exact; select_calls and other_calls within +2; wal_records within a 10% band; fetch_calls within 2x. msg/s, WAL bytes and total calls are informational (timing/FPI noise).

SQLAlchemy's async layer runs each statement in a greenlet, and the
tracer drops lines that run after an untracked switch. On Python 3.11,
which can't use sysmon, test_batched_flush_dlq_row_stays_inline lost a
line in about a third of runs and failed the 100% gate.
@lesnik512
lesnik512 force-pushed the refactor/seconds-interval branch from f4f2cf1 to bf2da54 Compare October 17, 2026 19:18
@lesnik512 lesnik512 changed the title refactor: build the server-side seconds interval in one helper refactor: one seconds-interval helper; coverage tracks greenlet switches Oct 17, 2026
@lesnik512
lesnik512 merged commit 84d9a66 into main Oct 17, 2026
13 checks passed
@lesnik512
lesnik512 deleted the refactor/seconds-interval branch October 17, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant