Skip to content

Commit 1682836

Browse files
committed
feat: Increase max polling attempts for image and video generation to improve reliability; implement adaptive polling delays
1 parent 6b0e432 commit 1682836

File tree

1 file changed

+30
-18
lines changed

1 file changed

+30
-18
lines changed

src/metaai_api/generation.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,8 @@ def generate_image(
336336
elif image_ids:
337337
self.logger.info(f"⏳ No URLs in SSE stream - fetching URLs for {len(image_ids)} images via polling...")
338338

339-
max_attempts = kwargs.pop('max_attempts', 25)
339+
# Increased to 30 attempts (~90s total) for better reliability
340+
max_attempts = kwargs.pop('max_attempts', 30)
340341
wait_seconds = kwargs.pop('wait_seconds', 3)
341342

342343
images = self.fetch_image_urls_by_media_id(
@@ -440,7 +441,8 @@ def generate_video(
440441
self.logger.info(f"Fetching URLs for {len(video_ids)} videos...")
441442

442443
# Extract max_attempts and wait_seconds from kwargs if present
443-
max_attempts = kwargs.pop('max_attempts', 12)
444+
# Increased to 24 attempts (120s total) to accommodate 50-60s video generation times
445+
max_attempts = kwargs.pop('max_attempts', 24)
444446
wait_seconds = kwargs.pop('wait_seconds', 5)
445447

446448
# Fetch video URLs using media ID approach
@@ -821,7 +823,7 @@ def fetch_video_urls_by_media_id(
821823
self,
822824
video_ids: List[str],
823825
conversation_id: Optional[str] = None,
824-
max_attempts: int = 12,
826+
max_attempts: int = 24,
825827
wait_seconds: int = 5
826828
) -> List[Dict[str, Any]]:
827829
"""
@@ -833,8 +835,8 @@ def fetch_video_urls_by_media_id(
833835
Args:
834836
video_ids: List of video IDs from generation
835837
conversation_id: Optional conversation ID for proper headers
836-
max_attempts: Maximum polling attempts (default: 12 = ~60s)
837-
wait_seconds: Seconds between attempts
838+
max_attempts: Maximum polling attempts (default: 24 = ~120s)
839+
wait_seconds: Base seconds between attempts (adaptive polling: 3s initially, 5s later)
838840
839841
Returns:
840842
List of video dictionaries with URLs, IDs, thumbnails, etc.
@@ -853,7 +855,9 @@ def fetch_video_urls_by_media_id(
853855
if 'error' in data:
854856
self.logger.warning(f"Attempt {attempt}/{max_attempts}: {data['error']}")
855857
if attempt < max_attempts:
856-
time.sleep(wait_seconds)
858+
# Adaptive polling: faster for first 10 attempts (30s), then slower
859+
adaptive_wait = 3 if attempt <= 10 else wait_seconds
860+
time.sleep(adaptive_wait)
857861
continue
858862

859863
# Extract videos from createRouteMedia and mediaLibraryFeed
@@ -921,13 +925,17 @@ def fetch_video_urls_by_media_id(
921925
self.logger.info(f"Attempt {attempt}/{max_attempts}: Videos not ready yet")
922926

923927
if attempt < max_attempts:
924-
self.logger.info(f"Waiting {wait_seconds}s before retry...")
925-
time.sleep(wait_seconds)
928+
# Adaptive polling: faster for first 10 attempts (30s), then slower
929+
adaptive_wait = 3 if attempt <= 10 else wait_seconds
930+
self.logger.info(f"Waiting {adaptive_wait}s before retry...")
931+
time.sleep(adaptive_wait)
926932

927933
except Exception as e:
928934
self.logger.warning(f"Attempt {attempt}/{max_attempts} failed: {e}")
929935
if attempt < max_attempts:
930-
time.sleep(wait_seconds)
936+
# Adaptive polling: faster for first 10 attempts (30s), then slower
937+
adaptive_wait = 3 if attempt <= 10 else wait_seconds
938+
time.sleep(adaptive_wait)
931939

932940
self.logger.warning(f"Video URLs not fully available after {max_attempts} attempts")
933941
return videos if 'videos' in locals() else []
@@ -936,7 +944,7 @@ def fetch_image_urls_by_media_id(
936944
self,
937945
image_ids: List[str],
938946
conversation_id: Optional[str] = None,
939-
max_attempts: int = 25,
947+
max_attempts: int = 30,
940948
wait_seconds: int = 3
941949
) -> List[Dict[str, Any]]:
942950
"""
@@ -948,8 +956,8 @@ def fetch_image_urls_by_media_id(
948956
Args:
949957
image_ids: List of image IDs from generation
950958
conversation_id: Optional conversation ID for proper headers
951-
max_attempts: Maximum polling attempts (default: 25 = ~75s)
952-
wait_seconds: Seconds between attempts (default: 3)
959+
max_attempts: Maximum polling attempts (default: 30 = ~90s with adaptive backoff)
960+
wait_seconds: Base seconds between attempts (adaptive: 2s → 3s → 4.5s)
953961
954962
Returns:
955963
List of image dictionaries with URLs, IDs, thumbnails, etc.
@@ -966,14 +974,16 @@ def fetch_image_urls_by_media_id(
966974
if not isinstance(data, dict):
967975
self.logger.warning("Attempt %s/%s: media response is not a dict", attempt, max_attempts)
968976
if attempt < max_attempts:
969-
delay = min(wait_seconds * (1 if attempt <= 5 else 1.3 if attempt <= 12 else 1.5), 6)
977+
# Adaptive: 2s (fast) → 3s (medium) → 4.5s (slower)
978+
delay = 2 if attempt <= 8 else (3 if attempt <= 18 else 4.5)
970979
time.sleep(delay)
971980
continue
972981

973982
if 'error' in data:
974983
self.logger.warning(f"Attempt {attempt}/{max_attempts}: {data['error']}")
975984
if attempt < max_attempts:
976-
delay = min(wait_seconds * (1 if attempt <= 5 else 1.3 if attempt <= 12 else 1.5), 6)
985+
# Adaptive: 2s (fast) → 3s (medium) → 4.5s (slower)
986+
delay = 2 if attempt <= 8 else (3 if attempt <= 18 else 4.5)
977987
time.sleep(delay)
978988
continue
979989

@@ -983,7 +993,8 @@ def fetch_image_urls_by_media_id(
983993
if not isinstance(data_root, dict):
984994
self.logger.warning("Attempt %s/%s: media response missing data field", attempt, max_attempts)
985995
if attempt < max_attempts:
986-
delay = min(wait_seconds * (1 if attempt <= 5 else 1.3 if attempt <= 12 else 1.5), 6)
996+
# Adaptive: 2s (fast) → 3s (medium) → 4.5s (slower)
997+
delay = 2 if attempt <= 8 else (3 if attempt <= 18 else 4.5)
987998
time.sleep(delay)
988999
continue
9891000

@@ -1061,15 +1072,16 @@ def fetch_image_urls_by_media_id(
10611072
self.logger.info(f"Attempt {attempt}/{max_attempts}: Images not ready yet")
10621073

10631074
if attempt < max_attempts:
1064-
# Progressive backoff: start fast, then slow down
1065-
delay = min(wait_seconds * (1 if attempt <= 3 else 1.5 if attempt <= 8 else 2), 5)
1075+
# Adaptive polling: 2s (fast) → 3s (medium) → 4.5s (slower)
1076+
delay = 2 if attempt <= 8 else (3 if attempt <= 18 else 4.5)
10661077
self.logger.info(f"Waiting {delay:.1f}s before retry...")
10671078
time.sleep(delay)
10681079

10691080
except Exception as e:
10701081
self.logger.warning(f"Attempt {attempt}/{max_attempts} failed: {e}")
10711082
if attempt < max_attempts:
1072-
delay = min(wait_seconds * (1 if attempt <= 5 else 1.3 if attempt <= 12 else 1.5), 6)
1083+
# Adaptive polling: 2s (fast) → 3s (medium) → 4.5s (slower)
1084+
delay = 2 if attempt <= 8 else (3 if attempt <= 18 else 4.5)
10731085
time.sleep(delay)
10741086

10751087
images_found = len(images) if 'images' in locals() else 0

0 commit comments

Comments
 (0)