Copy spanning locations and/or storage classes could not complete within 30 seconds. Please use the Rewrite method...ってなんだよ

PythonでGCSのファイルをコピーしようとしたらこんなエラーが出ました。

from google.cloud import storage

storage_client = storage.Client()

src_bucket = storage_client.bucket(BUCKET_NAME)
dst_bucket = storage_client.bucket(OUTPUT_BUCKET_NAME)

src_file_name = "hoge.gz"
dst_file_name = "hoge.gz"

src_blob = src_bucket.blob(src_file_name)

new_blob = dst_bucket.copy_blob(src_blob,
                                dst_bucket,
                                new_name=dst_file_name,
                                timeout=180)
new_blob.acl.save(src_blob.acl)

エラー内容

Copy spanning locations and/or storage classes could not complete within 30 seconds. Please use the Rewrite method (https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite) instead.

なんかtimeout=180も効いてないみたいです。

どうやらコピーしようとしているファイルが数GBと少々大きい場合このようなエラーが出るそうです。

メッセージにあるようにrewriteメソッドを使えとあります。

書き直してみました。

from google.cloud import storage

storage_client = storage.Client()

src_bucket = storage_client.bucket(BUCKET_NAME)
dst_bucket = storage_client.bucket(OUTPUT_BUCKET_NAME)

src_file_name = "hoge.gz"
dst_file_name = "hoge.gz"

src_blob = src_bucket.blob(src_file_name)
dst_blob = dst_bucket.blob(dst_file_name)

rewrite_token = None

while True:
  rewrite_token, bytes_rewritten, total_bytes = dst_blob.rewrite(src_blob,
                                                                 token=rewrite_token)
  progress_percent = (bytes_rewritten * 100) // total_bytes
  print(f"Progress : {bytes_rewritten} / {total_bytes} bytes {progress_percent}%.")

  if rewrite_token is None:
    print("Copy has done !!")
    break

実行してみると

Progress : 461373440 / 1899448698 bytes 24%.
Progress : 964689920 / 1899448698 bytes 50%.
Progress : 1509949440 / 1899448698 bytes 79%.
Progress : 1899448698 / 1899448698 bytes 100%.
Copy has done !!

気になったrewrite_tokenはなんかランダムな値でしたので省略します。

qiita.com