1414import base64
1515import hashlib
1616import requests
17- from io import BytesIO
17+ import sentry_sdk
1818
1919from .version import VERSION
20- from . studio_exception import StudioException
20+ from exceptions import *
2121
2222API_HEADER_KEY = 'X-SLT-API-KEY'
2323API_HEADER_CLIENT = 'X-SLT-API-CLIENT'
@@ -62,7 +62,7 @@ def __init__(self, api_key=None, **kwargs):
6262
6363 if 'debug' in kwargs :
6464 self .debug = kwargs ['debug' ]
65-
65+
6666 if 'max_concurrent_downloads' in kwargs :
6767 self .max_concurrent_downloads = kwargs ['max_concurrent_downloads' ]
6868
@@ -72,6 +72,19 @@ def __init__(self, api_key=None, **kwargs):
7272 LOGGER .debug ('Debug enabled' )
7373 LOGGER .propagate = True
7474
75+ # initialize sentry
76+ sentry_sdk .init (
77+ dsn = "https://[email protected] /4507850876452864" ,
78+ # Set traces_sample_rate to 1.0 to capture 100%
79+ # of transactions for tracing.
80+ traces_sample_rate = 1.0 ,
81+ # Set profiles_sample_rate to 1.0 to profile 100%
82+ # of sampled transactions.
83+ # We recommend adjusting this value in production.
84+ profiles_sample_rate = 1.0 ,
85+ ignore_errors = [JobNotFoundException , PhotoNotFoundException ]
86+ )
87+
7588 def _build_http_auth (self ):
7689 return (self .api_key , '' )
7790
@@ -302,14 +315,19 @@ def _upload_photo(self, photo_path, id, model='job'):
302315 photo_data = { f"{ model } _id" : id , "name" : photo_name , "use_cache_upload" : False }
303316
304317 if model == 'job' :
305- job_type = self .get_job (id )['type' ]
318+ job = self .get_job (id )
319+ if "type" in job :
320+ job_type = job ['type' ]
321+ if job_type == 'regular' :
322+ headers = { 'X-Amz-Tagging' : 'job=photo&api=true' }
323+ else :
324+ raise JobNotFoundException (f"Unable to find job with id: { id } " )
306325
307- if job_type == 'regular' :
308- headers = { 'X-Amz-Tagging' : 'job=photo&api=true' }
309326
310327 # Ask studio to create the photo record
311328 photo_resp = self ._create_photo (photo_data )
312- if not photo_resp :
329+
330+ if not 'id' in photo_resp :
313331 raise Exception ('Unable to create the photo object, if creating profile photo, ensure enable_extract and replace_background is set to: True' )
314332
315333 photo_id = photo_resp ['id' ]
@@ -329,28 +347,30 @@ def _upload_photo(self, photo_path, id, model='job'):
329347 # PUT request to presigned url with image data
330348 headers ["Content-MD5" ] = b64md5
331349
332- try :
333- upload_photo_resp = requests .put (upload_url , data , headers = headers )
334-
335- if not upload_photo_resp :
336- print ('First upload attempt failed, retrying...' )
337- retry = 0
338- # retry upload
339- while retry < 3 :
340- upload_photo_resp = requests .put (upload_url , data , headers = headers )
341-
342- if upload_photo_resp :
343- break # Upload was successful, exit the loop
344- elif retry == 2 : # Check if retry count is 2 (0-based indexing)
345- raise Exception ('Unable to upload to the bucket after retrying.' )
346- else :
347- time .sleep (1 ) # Wait for a moment before retrying
348- retry += 1
350+ retry = 0
351+ while retry < 3 :
352+ try :
353+ # attempt to upload the photo to aws
354+ upload_photo_resp = requests .put (upload_url , data , headers = headers )
349355
350- except Exception as e :
351- print (f"An exception of type { type (e ).__name__ } occurred: { e } " )
352- print ('Deleting created, but unuploaded photo...' )
353- self .delete_photo (photo_id )
356+ # Will raise exception for any statuses 4xx-5xx
357+ upload_photo_resp .raise_for_status ()
358+
359+ # if raise_for_status didn't throw an exception, then we successfully uploaded, exit the loop
360+ break
361+
362+ # rescue any exceptions in the loop
363+ except Exception as e :
364+ # if we've retried 3 times, delete the photo record and raise exception
365+ if retry == 2 :
366+ self .delete_photo (photo_id )
367+
368+ raise Exception (e )
369+ # if we haven't retried 3 times, wait for retry+1 seconds and continue the while loop
370+ else :
371+ print (f"Attempt #{ retry + 1 } to upload failed, retrying..." )
372+ retry += 1
373+ time .sleep (retry + 1 )
354374
355375 res ['upload_response' ] = upload_photo_resp .status_code
356376 return res
@@ -488,6 +508,9 @@ async def download_photo(self, photo_id, output_path, profile = None, options =
488508 await semaphore .acquire ()
489509
490510 photo = self .get_photo (photo_id )
511+
512+ if not 'job' in photo :
513+ raise PhotoNotFoundException (f"Unable to find photo with id: { photo_id } " )
491514 profile_id = photo ['job' ]['profileId' ]
492515 file_name = photo ['name' ]
493516
@@ -531,4 +554,3 @@ async def download_photo(self, photo_id, output_path, profile = None, options =
531554 finally :
532555 if semaphore != None :
533556 semaphore .release ()
534-
0 commit comments