3

dbサーバーから現在のタイムスタンプを取得するために使用される次のコードスニペットがあります。

class DbUtils:
    @staticmethod
    def get_current_timestamp():
        from django.db import connection
        cursor = connection.cursor()
        cursor.execute("SELECT CURRENT_TIMESTAMP")
        rows = cursor.fetchone()
        return rows[0]

このコードをテストするために、次のテストを作成しました。

def test_get_current_timestamp(self):
    ts_0 = DbUtils.get_current_timestamp()
    time.sleep(1)
    ts_1 = DbUtils.get_current_timestamp()
    delta_seconds = (ts_1 - ts_0).seconds
    assert 1 <= delta_seconds <= 3

このテストは合格しなかったので、少し掘り下げました。その理由は、への各呼び出しが毎回DbUtils.get_current_timestamp()同じ値を返すためでした。

In [31]: DbUtils.get_current_timestamp()
Out[31]: datetime.datetime(2012, 11, 1, 17, 17, 48, 950799, tzinfo=<UTC>)

# Wait a couple seconds

In [32]: DbUtils.get_current_timestamp()
Out[32]: datetime.datetime(2012, 11, 1, 17, 17, 48, 950799, tzinfo=<UTC>)

postgresqlログを監視しました-各クエリはデータベースにヒットしていました。

この作業を行うことができた唯一の方法は、django.db.transactionをインポートしtransaction.commit_unless_managed()て、SELECTを実行する前に実行することでした。get_current_timestampがどのコンテキストで呼び出されるかわからないため、SELECTの前にトランザクションをコミットすることは正しくないようです。これを修正する方法や回避する方法について何かアイデアはありますか?すべての相対時間の計算が正しく行われるようにするには、タイムスタンプをdbサーバーから取得する必要があります。

私は走っています:

Django==1.4.2
psycopg2==2.4.5 (with hstore extension via django-hstore==1.1.1)
PostgreSQL 9.1
4

1 に答える 1

3

同僚と話し合った後、Webリクエストごとに1つのタイムスタンプしか取得しないため、これは実際には望ましい動作である可能性があることに気付きました。いずれにせよ、私は通常、の戻り値を保存し、get_current_timestampその要求中のすべての操作にそれを使用していました。

テストに合格するには、次のことを行う必要がありました。

def test_get_current_timestamp(self):
    from django.db import transaction
    ts_0 = DbUtils.get_current_timestamp()
    transaction.commit_unless_managed()
    time.sleep(1)
    ts_1 = DbUtils.get_current_timestamp()
    transaction.commit_unless_managed()
    delta_seconds = (ts_1 - ts_0).seconds
    assert 1 <= delta_seconds <= 3

@a_horse_with_no_nameが指摘しているように、CURRENT_TIMESTAMPはトランザクションの開始時の時刻です。

于 2012-11-01T18:44:39.270 に答える