"""Logic for s3.""" from functools import cache import json import boto3 from botocore.exceptions import ClientError from src import config @cache def get_client(): """Get s3 client.""" return boto3.client('s3', config.AWS_REGION) def get_object_key(product_id, review_id): """Get object key.""" return f'snapshots/product-{product_id}-review-queue-{review_id}.json' def get_s3_url(bucket, object_key): """Get S3 URL for the given bucket and object key.""" return f's3://{bucket}/{object_key}' def wait_until_exists(object_key): """Wait until S3 object exists.""" boto3.resource('s3', config.AWS_REGION).Object( config.AWS_BUCKET_NAME, object_key ).wait_until_exists() def upload_snapshot(product, object_key): """Upload snapshot.""" http_code = None snapshot = json.dumps(product) try: s3_client = get_client() resp = s3_client.put_object( Bucket=config.AWS_BUCKET_NAME, Body=snapshot, Key=object_key, IfNoneMatch='*', # Create it only if object doesn't exist ContentType='application/json' ) http_code = resp['ResponseMetadata']['HTTPStatusCode'] except ClientError as e: http_code = e.response['ResponseMetadata']['HTTPStatusCode'] error_code = e.response['Error']['Code'] # do not raise for existing object code if error_code != 'PreconditionFailed': raise return http_code