from chalice import Chalice import boto3 from boto3 import resource from boto3.dynamodb.conditions import Key from boto3.dynamodb.conditions import Attr import json import uuid import random import logging import decimal import os app = Chalice(app_name='api-progress') logger = logging.getLogger('boto3') logger.setLevel(logging.INFO) VERSION = 'v1' # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): return str(o) return super(DecimalEncoder, self).default(o) # The boto3 dynamoDB resource dynamodb_resource = resource('dynamodb') @app.route('/', methods=['GET'], cors=True) def index(): DYNAMO_TABLE_NAME = os.environ['JobTable'] return {'DYNAMO_TABLE_NAME': DYNAMO_TABLE_NAME} @app.route('/progress/job/{jobId}', methods=['GET'], cors=True) def job_progress(jobId): DYNAMO_TABLE_NAME = os.environ['JobTable'] DYNAMO_INDEX_NAME = 'id-createdAt-index' logger.info('GET progress for {} from {}'.format(jobId, DYNAMO_TABLE_NAME)) try: table = dynamodb_resource.Table(DYNAMO_TABLE_NAME) response = table.query(IndexName=DYNAMO_INDEX_NAME, KeyConditionExpression=Key('id').eq(jobId)) except ClientError as e: logger.info("ClientError from Dynamodb {}".format(e.response['Error']['Message'])) raise BadRequestError("Dynamodb returned error message '%s'" % e.response['Error']['Message']) except Exception as e: logger.info("ClientError from Dynamodb {}".format(e.response['Error']['Message'])) raise ChaliceViewError("Dynamodb returned error message '%s'" % e.response['Error']['Message']) print (json.dumps(response, cls=DecimalEncoder)) # there is no information about this job yet if response['Count'] > 0: return response['Items'][0] else: return {} @app.route('/progress/status/{status}', methods=['GET'], cors=True) def status_progress(status): DYNAMO_TABLE_NAME = os.environ['JobTable'] logger.info('GET progress for jobs with status {} from {}'.format(status, DYNAMO_TABLE_NAME)) table = dynamodb_resource.Table(DYNAMO_TABLE_NAME) response = table.query( IndexName='status-createdAt-index', KeyConditionExpression=Key('status').eq(status), ScanIndexForward=False ) items = response['Items'] while True: print(len(response['Items'])) if response.get('LastEvaluatedKey'): response = table.scan( ExclusiveStartKey=response['LastEvaluatedKey'], IndexName='status-createdAt-index', KeyConditionExpression=Key('status').eq(status), ScanIndexForward=False ) items += response['Items'] else: break return items # The view function above will return {"hello": "world"} # whenever you make an HTTP GET request to '/'. # # Here are a few more examples: # # @app.route('/hello/{name}') # def hello_name(name): # # '/hello/james' -> {"hello": "james"} # return {'hello': name} # # @app.route('/users', methods=['POST']) # def create_user(): # # This is the JSON body the user sent in their POST request. # user_as_json = app.current_request.json_body # # We'll echo the json body back to the user in a 'user' key. # return {'user': user_as_json} # # See the README documentation for more examples. #