Amazon RDSのスナップショットをboto3のWaiterで作成待ちをするとき注意点

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

サーモン大好き横山です。

今回はRDSの db_snapshot_completed のWaiterを使ってて出くわしたエラーと対策(暫定)を紹介しようと思います。

boto3のバージョンは以下を使用しています。

$ pip freeze
…
boto3==1.2.3
botocore==1.3.23
…

症状

通常、Amazon RDSのスナップショットは体感ですが、大体2〜3分で終わります。
ですが、終わらない時は1時間かけて終わることもあります。 db_snapshot_completed のWaiterが10分ぐらいかかると、 WaiterError: Waiter DBSnapshotCompleted failed: Max attempts exceeded がthrowされてスナップショット取得完了前に処理を抜けてしまいます。

コード例

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from __future__ import print_function
from datetime import datetime
from traceback import format_exc

import boto3

def now_string(dt_format="%Y/%m/%d %H:%M:%S"):
    return datetime.now().strftime(dt_format)

def output(s):
    print('[{}] {}'.format(now_string(), s))

rds_id = 'rds_id'
snapshot_name = 'snapshot_name'

rds = boto3.client('rds')

output('create snapshot')
self.rds.create_db_snapshot(DBInstanceIdentifier=rds_id,
                            DBSnapshotIdentifier=snapshot_name)

snapshot_waiter = rds.get_waiter('db_snapshot_completed')
try:
    snapshot_waiter.wait(DBInstanceIdentifier=rds_id,
                         DBSnapshotIdentifier=snapshot_name)
except:
    output(format_exc())

エラー例

※コード例での再現が難しかったので実際起きたエラー出力を貼り付けてます。

[2016/02/29 13:10:25] create snapshot
[2016/02/29 13:20:14] Traceback (most recent call last):
  File "main.py", line 170, in run
    func1(DB_INSTANCE_IDENTIFIER, DB_SNAPSHOT_NAME)
  File "/home/ec2-user/xxx.py", line 33, in func1
    DBSnapshotIdentifier=snapshot_name
  File "/home/ec2-user/venv/local/lib/python2.7/site-packages/botocore/waiter.py", line 53, in wait
    Waiter.wait(self, **kwargs)
  File "/home/ec2-user/venv/local/lib/python2.7/site-packages/botocore/waiter.py", line 315, in wait
    reason='Max attempts exceeded')
WaiterError: Waiter DBSnapshotCompleted failed: Max attempts exceeded

対処方法

Whileループを使わずにかけるのがWaiterの利点だと思ったのですが、使わないと上手く処理が書けなかったので仕方なく。
もっとスマートな解決方法があれば教えてください!

snapshot_waiter = rds.get_waiter('db_snapshot_completed')
while True:
    try:
        snapshot_waiter.wait(DBInstanceIdentifier=rds_id,
                             DBSnapshotIdentifier=snapshot_name)
    except:
        output(format_exc())
        continue
    break

まとめ

他のWaiterでは今の所 WaiterError に遭遇していません。
RDSのスナップショットで10分以上かかる処理でWaiterを書くときは注意して書く必要がありそうです。

最後に私事となりますが、四季 花まる 時計台店 の「サーモンユッケ」と「サーモンの握り」がとても美味しかったのでこの場を借りて紹介して〆よう思います。

rds_waiter_01

rds_waiter_02