Postgres: TIMESTAMP WITHOUT TIME ZONE + java.sql.Timestamp stores JVM-local time; mixed-TZ fleets/DST corrupt ordering, lag, purge

オープン
#135 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
kotlin, postgresql
領域
databases

調査の方向性

Start with PostgresOutboxStore, which binds created_at, updated_at and last_attempt with setTimestamp and reads them back with getTimestamp, and with the Postgres schema changesets that declare these columns as TIMESTAMP. Add a migration that converts the columns to timestamptz, then switch the store to OffsetDateTime binding and reading. Done when a test passes with a non-UTC TimeZone.setDefault and the migration path for existing users is documented.

索引モデルが issue の本文から書いたものです。

説明

breaking-change bug

Severity: Medium · Area: okapi-postgres schema and JDBC mapping · Found in: code review of main @ e5630a1 (reasoned from pgjdbc semantics, not reproduced)

Problem

The Postgres schema declares created_at, updated_at and last_attempt as TIMESTAMP (without time zone). PostgresOutboxStore writes them with setTimestamp(Timestamp.from(instant)) and reads them with getTimestamp(...).toInstant(). pgjdbc renders a java.sql.Timestamp in the JVM default time zone, so the column stores local wall-clock time of whichever JVM wrote the row:

  • Mixed-TZ fleets (e.g. one pod with TZ=Europe/Warsaw, others UTC, or a developer laptop pointed at a shared DB):
    • ORDER BY created_at is skewed by hours
    • the lag gauge (okapi.entries.lag.seconds) is off by hours, possibly negative
    • the purger's last_attempt < cutoff deletes DELIVERED rows hours early or keeps them hours late
  • DST fall-back in a non-UTC zone: an hour of local times repeats, so two different instants map to the same stored value. Ordering and lag are wrong for that hour, and reading back can shift values by 1 h.

MySQL TIMESTAMP(6) normalizes to UTC, so this mainly affects Postgres.

Suggested fix

Migrate the columns to TIMESTAMPTZ (changeset 002 with ALTER COLUMN ... TYPE timestamptz USING ... AT TIME ZONE '<zone that wrote the data>', documented for existing users). Bind with setObject(i, instant.atOffset(ZoneOffset.UTC)) and read with getObject(col, OffsetDateTime::class.java). Add a test that runs the store with a non-UTC TimeZone.setDefault.

主要言語
Kotlin
スター
14
フォーク
0
平均マージ
9時間 54分
マージ済み PR(30日)
11

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

softwaremill/okapi のほかの issue

softwaremill/okapi の issue をすべて見る

似ている issue

Kotlin の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。