mirror of
https://github.com/binwiederhier/ntfy.git
synced 2026-11-10 14:44:04 +08:00
Round the Postgres clock down to the second, like SQLite
This commit is contained in:
1 parent
6674f3b5bd
commit
6a573ab5c1
2 files changed
+30
-3
No files matched your search
@@ -6,15 +6,16 @@ import (
|
||||
"heckel.io/ntfy/v2/db"
|
||||
)
|
||||
|
||||
// Timestamps come from the database clock, never from a node's (see Store). The upsert is one
|
||||
// Timestamps come from the database clock, never from a node's (see Store), rounded down to the
|
||||
// second like SQLite's. The upsert is one
|
||||
// fixed statement per chunk (unnest), because SQL built per call bloats pgx's statement cache.
|
||||
// Same period: add; a newer one: replace; an older one (a leftover): add to the stored period.
|
||||
const (
|
||||
postgresSelectClockQuery = `SELECT EXTRACT(EPOCH FROM now())::BIGINT`
|
||||
postgresSelectClockQuery = `SELECT FLOOR(EXTRACT(EPOCH FROM now()))::BIGINT`
|
||||
postgresSelectSinceQuery = `SELECT key, period_start, messages, emails, calls FROM usage WHERE updated_at >= $1`
|
||||
postgresUpsertQuery = `
|
||||
INSERT INTO usage AS u (key, period_start, messages, emails, calls, updated_at)
|
||||
SELECT key, ps, m, e, c, EXTRACT(EPOCH FROM now())::BIGINT
|
||||
SELECT key, ps, m, e, c, FLOOR(EXTRACT(EPOCH FROM now()))::BIGINT
|
||||
FROM unnest($1::TEXT[], $2::BIGINT[], $3::BIGINT[], $4::BIGINT[], $5::BIGINT[]) AS d(key, ps, m, e, c)
|
||||
ON CONFLICT (key) DO UPDATE SET
|
||||
messages = CASE WHEN u.period_start >= EXCLUDED.period_start THEN u.messages + EXCLUDED.messages ELSE EXCLUDED.messages END,
|
||||
|
||||
@@ -212,3 +212,29 @@ func keysOf(rows map[string]usageRow) []string {
|
||||
slices.Sort(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
func TestStore_ClockTruncatesToTheSecond(t *testing.T) {
|
||||
// Database time is whole seconds, rounded down on both dialects, for the clock and for
|
||||
// updated_at alike (the test database runs on this host's clock)
|
||||
forEachBackend(t, func(t *testing.T, newStore func() *Store) {
|
||||
s := newStore()
|
||||
ctx := context.Background()
|
||||
for i := 0; i < 20; i++ {
|
||||
dbNow, err := s.clock(ctx)
|
||||
require.Nil(t, err)
|
||||
require.LessOrEqual(t, dbNow, time.Now().Unix())
|
||||
_, err = s.write(ctx, []usageRow{
|
||||
{
|
||||
key: "k",
|
||||
periodStart: 1,
|
||||
counts: [numDaily]int64{1, 0, 0},
|
||||
},
|
||||
})
|
||||
require.Nil(t, err)
|
||||
var updatedAt int64
|
||||
require.Nil(t, s.db.QueryRow(`SELECT updated_at FROM usage WHERE key = 'k'`).Scan(&updatedAt))
|
||||
require.LessOrEqual(t, updatedAt, time.Now().Unix())
|
||||
time.Sleep(37 * time.Millisecond)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user