@@ -48,35 +48,52 @@ def detect_timeout(sender, task, **kwargs):
48
48
49
49
def async_analysis (checksum , api , file_name , func , * args , ** kwargs ):
50
50
"""Async Analysis Task."""
51
- # Check if the task is already completed
51
+ # Check if the scan is already completed and successful
52
+ scan_completed = False
52
53
recent = RecentScansDB .objects .filter (MD5 = checksum )
53
- scan_completed = recent [0 ].APP_NAME or recent [0 ].PACKAGE_NAME
54
- # Check if the task is updated within the last 60 minutes
55
- active_recently = recent [0 ].TIMESTAMP >= timezone .now () - timedelta (
56
- minutes = settings .ASYNC_ANALYSIS_TIMEOUT )
54
+ if recent .exists () and (recent [0 ].APP_NAME or recent [0 ].PACKAGE_NAME ):
55
+ # Successful scan will have APP_NAME or PACKAGE_NAME
56
+ scan_completed = True
57
+ # Check if task is already completed within the last 60 minutes
58
+ # Can be success or failed
59
+ completed_at_recently = EnqueuedTask .objects .filter (
60
+ checksum = checksum ,
61
+ completed_at__gte = timezone .now () - timedelta (
62
+ minutes = settings .ASYNC_ANALYSIS_TIMEOUT ),
63
+ ).exists ()
64
+
57
65
# Check if the task is already enqueued within the last 60 minutes
58
66
queued_recently = EnqueuedTask .objects .filter (
59
67
checksum = checksum ,
60
68
created_at__gte = timezone .now () - timedelta (
61
69
minutes = settings .ASYNC_ANALYSIS_TIMEOUT ),
62
70
).exists ()
71
+ # Check if the task is already started within the last 60 minutes
72
+ started_at_recently = EnqueuedTask .objects .filter (
73
+ checksum = checksum ,
74
+ started_at__gte = timezone .now () - timedelta (
75
+ minutes = settings .ASYNC_ANALYSIS_TIMEOUT ),
76
+ ).exists ()
63
77
64
- # Additional checks on recent queue
65
- if queued_recently :
66
- if scan_completed :
67
- # scan already completed recently
68
- msg = 'Analysis already completed in the last 60 minutes'
69
- logger .warning (msg )
70
- if api :
71
- return {'task_id' : None , 'message' : msg }
72
- return HttpResponseRedirect ('/tasks?q=completed' )
73
- elif active_recently :
74
- # scan not completed but active recently
75
- msg = 'Analysis already enqueued in the last 60 minutes'
76
- logger .warning (msg )
77
- if api :
78
- return {'task_id' : None , 'message' : msg }
79
- return HttpResponseRedirect ('/tasks?q=queued' )
78
+ # Prevent duplicate scans in the last 60 minutes
79
+ if scan_completed and completed_at_recently :
80
+ # scan task already completed with success/failure recently
81
+ msg = ('Analysis already completed/failed in the '
82
+ f'last { settings .ASYNC_ANALYSIS_TIMEOUT } minutes. '
83
+ 'Please try again later.' )
84
+ logger .warning (msg )
85
+ if api :
86
+ return {'task_id' : None , 'message' : msg }
87
+ return HttpResponseRedirect ('/tasks?q=completed' )
88
+ elif queued_recently or started_at_recently :
89
+ # scan not completed but queued or started recently
90
+ msg = ('Analysis already enqueued in the '
91
+ f'last { settings .ASYNC_ANALYSIS_TIMEOUT } minutes. '
92
+ 'Please wait for the current scan to complete.' )
93
+ logger .warning (msg )
94
+ if api :
95
+ return {'task_id' : None , 'message' : msg }
96
+ return HttpResponseRedirect ('/tasks?q=queued' )
80
97
81
98
# Clear old tasks
82
99
queue_size = settings .QUEUE_MAX_SIZE
@@ -108,15 +125,15 @@ def async_analysis(checksum, api, file_name, func, *args, **kwargs):
108
125
return HttpResponseRedirect ('/tasks' )
109
126
110
127
111
- def enqueued_task_init (checksum ):
112
- """Store Task start ."""
128
+ def mark_task_started (checksum ):
129
+ """Register the enqued task and others that matches the checksum as started ."""
113
130
EnqueuedTask .objects .filter (checksum = checksum ).update (
114
131
started_at = timezone .now (),
115
132
)
116
133
117
134
118
- def update_enqueued_task (checksum , app_name , status ):
119
- """Update the Enqueued Task and others that matches the checksum."""
135
+ def mark_task_completed (checksum , app_name , status ):
136
+ """Update the enqueued task and others that matches the checksum as completed ."""
120
137
EnqueuedTask .objects .filter (checksum = checksum ).update (
121
138
app_name = app_name [:254 ],
122
139
completed_at = timezone .now (),
0 commit comments