AI AUtomtaion, Schudelign and publishign fromt and backe end refoactr
This commit is contained in:
@@ -63,7 +63,7 @@ class AutomationService:
|
||||
|
||||
def _check_should_stop(self) -> tuple[bool, str]:
|
||||
"""
|
||||
Check if automation should stop (paused or cancelled)
|
||||
Check if automation should stop (paused, cancelled, or credit budget exceeded)
|
||||
|
||||
Returns:
|
||||
(should_stop, reason)
|
||||
@@ -79,6 +79,83 @@ class AutomationService:
|
||||
elif self.run.status == 'cancelled':
|
||||
return True, "cancelled"
|
||||
|
||||
# Check credit budget
|
||||
budget_exceeded, budget_reason = self._check_credit_budget()
|
||||
if budget_exceeded:
|
||||
return True, f"credit_budget_exceeded: {budget_reason}"
|
||||
|
||||
return False, ""
|
||||
|
||||
def _get_per_run_limit(self, stage: int) -> int:
|
||||
"""
|
||||
Get the per-run item limit for a stage from config.
|
||||
|
||||
Args:
|
||||
stage: Stage number (1-7)
|
||||
|
||||
Returns:
|
||||
Max items to process (0 = unlimited)
|
||||
"""
|
||||
limit_map = {
|
||||
1: self.config.max_keywords_per_run,
|
||||
2: self.config.max_clusters_per_run,
|
||||
3: self.config.max_ideas_per_run,
|
||||
4: self.config.max_tasks_per_run,
|
||||
5: self.config.max_content_per_run,
|
||||
6: self.config.max_images_per_run,
|
||||
7: self.config.max_approvals_per_run,
|
||||
}
|
||||
return limit_map.get(stage, 0)
|
||||
|
||||
def _apply_per_run_limit(self, queryset, stage: int, log_prefix: str = ""):
|
||||
"""
|
||||
Apply per-run limit to queryset if configured.
|
||||
|
||||
Args:
|
||||
queryset: Django queryset to limit
|
||||
stage: Stage number (1-7)
|
||||
log_prefix: Prefix for log messages
|
||||
|
||||
Returns:
|
||||
Limited queryset (or list if limit applied)
|
||||
"""
|
||||
limit = self._get_per_run_limit(stage)
|
||||
|
||||
if limit > 0:
|
||||
total = queryset.count()
|
||||
if total > limit:
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
stage, f"{log_prefix}Applying per-run limit: {limit} of {total} items (limit set in automation config)"
|
||||
)
|
||||
return list(queryset[:limit])
|
||||
|
||||
return queryset
|
||||
|
||||
def _check_credit_budget(self) -> tuple[bool, str]:
|
||||
"""
|
||||
Check if credit budget for this run has been exceeded.
|
||||
|
||||
Returns:
|
||||
(exceeded, reason) - If exceeded is True, automation should stop
|
||||
"""
|
||||
if not self.run or not self.config:
|
||||
return False, ""
|
||||
|
||||
max_credits = self.config.max_credits_per_run
|
||||
if max_credits <= 0: # 0 = unlimited
|
||||
return False, ""
|
||||
|
||||
credits_used = self._get_credits_used()
|
||||
|
||||
if credits_used >= max_credits:
|
||||
reason = f"Credit budget exhausted: {credits_used}/{max_credits} credits used"
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
self.run.current_stage, reason
|
||||
)
|
||||
return True, reason
|
||||
|
||||
return False, ""
|
||||
|
||||
def start_automation(self, trigger_type: str = 'manual') -> str:
|
||||
@@ -170,6 +247,19 @@ class AutomationService:
|
||||
disabled=False
|
||||
)
|
||||
|
||||
# Apply per-run limit (0 = unlimited)
|
||||
per_run_limit = self._get_per_run_limit(stage_number)
|
||||
total_available = pending_keywords.count()
|
||||
|
||||
if per_run_limit > 0 and total_available > per_run_limit:
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
stage_number, f"Per-run limit: Processing {per_run_limit} of {total_available} keywords"
|
||||
)
|
||||
# Get limited keyword IDs first, then filter queryset
|
||||
limited_ids = list(pending_keywords.values_list('id', flat=True)[:per_run_limit])
|
||||
pending_keywords = pending_keywords.filter(id__in=limited_ids)
|
||||
|
||||
total_count = pending_keywords.count()
|
||||
|
||||
# IMPORTANT: Group keywords by sector to avoid mixing sectors in clustering
|
||||
@@ -480,6 +570,17 @@ class AutomationService:
|
||||
disabled=False
|
||||
)
|
||||
|
||||
# Apply per-run limit (0 = unlimited)
|
||||
per_run_limit = self._get_per_run_limit(stage_number)
|
||||
total_available = pending_clusters.count()
|
||||
|
||||
if per_run_limit > 0 and total_available > per_run_limit:
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
stage_number, f"Per-run limit: Processing {per_run_limit} of {total_available} clusters"
|
||||
)
|
||||
pending_clusters = pending_clusters[:per_run_limit]
|
||||
|
||||
total_count = pending_clusters.count()
|
||||
|
||||
# Log stage start
|
||||
@@ -674,6 +775,17 @@ class AutomationService:
|
||||
status='new'
|
||||
)
|
||||
|
||||
# Apply per-run limit (0 = unlimited)
|
||||
per_run_limit = self._get_per_run_limit(stage_number)
|
||||
total_available = pending_ideas.count()
|
||||
|
||||
if per_run_limit > 0 and total_available > per_run_limit:
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
stage_number, f"Per-run limit: Processing {per_run_limit} of {total_available} ideas"
|
||||
)
|
||||
pending_ideas = pending_ideas[:per_run_limit]
|
||||
|
||||
total_count = pending_ideas.count()
|
||||
|
||||
# Log stage start
|
||||
@@ -837,6 +949,17 @@ class AutomationService:
|
||||
status='queued'
|
||||
)
|
||||
|
||||
# Apply per-run limit (0 = unlimited)
|
||||
per_run_limit = self._get_per_run_limit(stage_number)
|
||||
total_available = pending_tasks.count()
|
||||
|
||||
if per_run_limit > 0 and total_available > per_run_limit:
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
stage_number, f"Per-run limit: Processing {per_run_limit} of {total_available} tasks"
|
||||
)
|
||||
pending_tasks = pending_tasks[:per_run_limit]
|
||||
|
||||
total_count = pending_tasks.count()
|
||||
|
||||
# Log stage start
|
||||
@@ -1078,6 +1201,17 @@ class AutomationService:
|
||||
images_count=0
|
||||
)
|
||||
|
||||
# Apply per-run limit (0 = unlimited)
|
||||
per_run_limit = self._get_per_run_limit(stage_number)
|
||||
total_available = content_without_images.count()
|
||||
|
||||
if per_run_limit > 0 and total_available > per_run_limit:
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
stage_number, f"Per-run limit: Processing {per_run_limit} of {total_available} content items"
|
||||
)
|
||||
content_without_images = content_without_images[:per_run_limit]
|
||||
|
||||
total_count = content_without_images.count()
|
||||
|
||||
# ADDED: Enhanced logging
|
||||
@@ -1291,6 +1425,17 @@ class AutomationService:
|
||||
status='pending'
|
||||
)
|
||||
|
||||
# Apply per-run limit (0 = unlimited)
|
||||
per_run_limit = self._get_per_run_limit(stage_number)
|
||||
total_available = pending_images.count()
|
||||
|
||||
if per_run_limit > 0 and total_available > per_run_limit:
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
stage_number, f"Per-run limit: Processing {per_run_limit} of {total_available} images"
|
||||
)
|
||||
pending_images = pending_images[:per_run_limit]
|
||||
|
||||
total_count = pending_images.count()
|
||||
|
||||
# Log stage start
|
||||
@@ -1538,6 +1683,17 @@ class AutomationService:
|
||||
status='review'
|
||||
)
|
||||
|
||||
# Apply per-run limit (0 = unlimited)
|
||||
per_run_limit = self._get_per_run_limit(stage_number)
|
||||
total_available = ready_for_review.count()
|
||||
|
||||
if per_run_limit > 0 and total_available > per_run_limit:
|
||||
self.logger.log_stage_progress(
|
||||
self.run.run_id, self.account.id, self.site.id,
|
||||
stage_number, f"Per-run limit: Approving {per_run_limit} of {total_available} content items"
|
||||
)
|
||||
ready_for_review = ready_for_review[:per_run_limit]
|
||||
|
||||
total_count = ready_for_review.count()
|
||||
|
||||
# Log stage start
|
||||
|
||||
Reference in New Issue
Block a user