-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
129 lines (104 loc) · 5.71 KB
/
Copy pathapp.py
File metadata and controls
129 lines (104 loc) · 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
from fastapi import FastAPI, HTTPException, BackgroundTasks
from fastapi.responses import JSONResponse, RedirectResponse, FileResponse
import uuid,uvicorn,boto3,os,redis,botocore
from calcUtils import calculations
from dotenv import load_dotenv
app = FastAPI()
load_dotenv()
AWS_ACCESS_KEY = os.getenv('AWS_ACCESS')
AWS_SECRET_KEY = os.getenv('AWS_SECRET')
REDIS_HOST = os.getenv('REDIS_HOST', 'localhost')
REDIS_PASSWORD = os.getenv('REDIS_PASSWORD')
PORT = os.getenv('PORT', 8000)
# Redis dictionary to store the status of each report
r = redis.Redis(host=REDIS_HOST,port=16139,password=REDIS_PASSWORD)
# Initialize the S3 client
s3 = boto3.client('s3', aws_access_key_id=AWS_ACCESS_KEY, aws_secret_access_key=AWS_SECRET_KEY, region_name='ap-southeast-2')
def calculations_wrapper(report_id):
try:
# Call the calculations function
calculations(report_id)
# Update the status of the report in Redis
r.set(str(report_id), 'Completed')
except Exception as e:
r.set(str(report_id), f'Error: {str(e)}')
@app.get('/')
def home():
resp ={"message":"Welcome to the Loop Report Generation API. To trigger the report generation, use the /trigger_reportgen endpoint.",
"endpoints":{"/trigger_reportgen":"Triggers the report generation process and returns the report ID.",
"/status/{report_id}":"Returns the status of the report with the given report ID. If the report is completed, the report file will be downloaded."},
"example":"https://loop-api200-7278760e7ad4.herokuapp.com/trigger_reportgen",
}
return JSONResponse(status_code=200,content=resp)
@app.get('/trigger_reportgen')
def reportgen(background_tasks: BackgroundTasks):
try:
# Generate a unique report ID
report_id = uuid.uuid4()
# Start the calculations for the report in the background
background_tasks.add_task(calculations_wrapper, report_id)
# Update the status of the report in Redis
r.set(str(report_id), 'In progress')
# Return the report ID
output = {"message":"Report Generation has been triggered. Use the /status/{report_id} endpoint to check the status of the report.",
"report_id":str(report_id),
"file_name":f'output_{report_id}.csv',
"details":"The report is being generated in the background. To conserve compute power(Limited Resources On Free Instance) the number of stores to be reported have been limited to 5. The report will be available at the get_report endpoint shortly.Get Report Status at the URL below",
"status_url":f"https://loop-api200-7278760e7ad4.herokuapp.com/status/{report_id}",
}
return JSONResponse(status_code=200,content=output)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get('/status/{report_id}')
def get_return(report_id: str):
# Return the status of the report
status = r.get(report_id)
if status is None:
return JSONResponse(status_code=404, content={"status": status, "message":"Report ID not found. Please check the report ID and try again."})
else:
status = status.decode('utf-8')
if status == 'In progress':
return JSONResponse(status_code=200, content={"status": status+"...",
"message":"Please wait for the report to be generated. On Completion, You will get the download url for the file."})
else:
file_name = f'output_{report_id}.csv'
# Check if the file exists in S3
try:
response = s3.head_object(Bucket='testbucket-debam', Key=file_name)
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == '404':
return JSONResponse(status_code=404, content={"status": status, "message":"File not found in S3. Please check the file name and try again."})
else:
# Something else has gone wrong.
raise
# Get the file from S3
obj = s3.get_object(Bucket='testbucket-debam', Key=file_name)
# Get the last modified time
last_modified = response['LastModified']
# Read the file content
file_content = obj['Body'].read().decode('utf-8')
file_contents = file_content.split('\n')
output = {"status": status,
"report_id": report_id,
"report_time": last_modified.strftime('%Y-%m-%d %H:%M:%S'),
"message":"The report has been generated successfully. Use the download_url or hit the /download/{report_id} endpoint to download the report file.",
"download_url": f"https://loop-api200-7278760e7ad4.herokuapp.com/download/{report_id}",
"Note":"The report is generated with a limit of 5 stores to conserve resources. The full report can be generated by changing the limit in the code.",
"File Content": file_contents,
}
return JSONResponse(status_code=200, content=output)
@app.get('/download/{report_id}')
def download_report(report_id: str):
file_name = f'output_{report_id}.csv'
# Generate a presigned URL for the S3 object
url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': 'testbucket-debam', 'Key': file_name},
ExpiresIn=3600)
# Redirect to the presigned URL
return RedirectResponse(url)
@app.get('/favicon.ico', include_in_schema=False)
async def favicon():
return FileResponse('favicon.ico')
# if __name__ == '__main__':
# uvicorn.run(app, port=PORT, host='0.0.0.0')