Skip to content

Commit c35bcae

Browse files
authored
Merge pull request #613 from openedx/pwnage101/add-job-results-url
feat: local_license_enrollment.py: add job results URL to logging and output file
2 parents d50a080 + c5a3cec commit c35bcae

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

scripts/local_license_enrollment.py

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
--enterprise-uuid=<uuid> \
2020
--output-file=local-enrollment-output.csv \
2121
--environment=local \
22-
--sleep-interval=5 \
2322
--fetch-jwt
2423
```
2524
@@ -30,18 +29,18 @@
3029
* ``--enterprise-uuid`` The UUID of the enterprise to which all enrollments are associated.
3130
3231
* ``--output-file`` is where results of the call to the bulk-license-enrollment view are stored. It'll be a headerless
33-
CSV with three columns: ``chunk_id``, ``job_id``, ``email``.
32+
CSV with three columns: ``chunk_id``, ``job_id``, ``email``, ``job_results_url``.
3433
3534
* ``--chunk-size`` Number of emails contained in each chunk. Default and max is 1000.
3635
3736
* ``--environment`` Which environment to execute against. Choices are 'local', 'stage', or 'prod'.
3837
39-
* ``--sleep-interval`` is how long to wait between chunk deliveries, in seconds. Each chunk of this script causes one
40-
asynchronous bulk enrollment task to be queued, so this interval is the primary way of controlling concurrency. If
41-
``--sleep-interval`` is too high, operational risk is low but enrollment of all learners may take too long. If
42-
``--sleep-interval`` is too low, a couple of risks arise: 1) we risk overwhelming the license_manager.bulk_enrollment
43-
dedicated celery queue, and 2) completion rate may be slower than task creation, increasing risk of accumulating more
44-
failed tasks before manually terminating the script.
38+
* ``--sleep-interval`` is how long to wait between chunk deliveries, in seconds (default = 120). Each chunk of this
39+
script causes one asynchronous bulk enrollment task to be queued, so this interval is the primary way of controlling
40+
concurrency. If ``--sleep-interval`` is too high, operational risk is low but enrollment of all learners may take too
41+
long. If ``--sleep-interval`` is too low, a couple of risks arise: 1) we risk overwhelming the
42+
license_manager.bulk_enrollment dedicated celery queue, and 2) completion rate may be slower than task creation,
43+
increasing risk of accumulating more failed tasks before manually terminating the script.
4544
"""
4645
from collections import defaultdict
4746
import csv
@@ -50,6 +49,7 @@
5049

5150
import click
5251
import requests
52+
from requests.models import PreparedRequest
5353

5454

5555
# 1000 is currently the maximum number of emails allowed by the bulk-license-enrollment API endpoint. (I didn't actually
@@ -112,7 +112,7 @@ def get_already_processed_emails(results_file):
112112
already_processed_emails = {}
113113
with open(results_file, 'r') as f_in:
114114
reader = csv.reader(f_in, delimiter=',')
115-
for (chunk_id, _, email_address) in reader:
115+
for (chunk_id, _, email_address, _) in reader:
116116
already_processed_emails[email_address] = chunk_id
117117
return already_processed_emails
118118

@@ -220,18 +220,32 @@ def request_enrollments(
220220

221221
response_data = response.json()
222222

223+
# Use the requests library to generate a URL to fetch job results, but not actually call it.
224+
req = PreparedRequest()
225+
req.prepare_url(
226+
url,
227+
{
228+
'enterprise_customer_uuid': enterprise_uuid,
229+
'bulk_enrollment_job_uuid': response_data['job_id'],
230+
},
231+
)
232+
job_results_url = req.url
233+
223234
results_for_chunk = []
224235
for email in emails_for_chunk:
225236
results_for_chunk.append([
226237
str(chunk_id),
227238
str(response_data['job_id']),
228239
email,
240+
job_results_url,
229241
])
230242

231-
print('Generated BulkEnrollmentJob UUID:', response_data['job_id'])
232243
print(
233-
f'Successfully sent bulk enrollment request for chunk_id {chunk_id} and course_run_key {course_run_key} with '
234-
f'{len(emails_for_chunk)} emails'
244+
f'Successfully sent bulk enrollment request containing {len(emails_for_chunk)} emails. '
245+
f'chunk_id = {chunk_id}, '
246+
f'course_run_key = {course_run_key}, '
247+
f'BulkEnrollmentJob UUID = {response_data["job_id"]}, '
248+
f'job results URL = {job_results_url}'
235249
)
236250

237251
return results_for_chunk
@@ -275,7 +289,14 @@ def do_enrollment_for_chunk(
275289
print(f'Sleeping for {sleep_interval} seconds.')
276290
time.sleep(sleep_interval)
277291
else:
278-
print('No enrollments need to be created for chunk_id', chunk_id, 'with size', len(email_chunk))
292+
print(
293+
'No enrollments need to be created for chunk_id',
294+
chunk_id,
295+
'with size',
296+
len(email_chunk),
297+
'and course_run_key',
298+
course_run_key,
299+
)
279300

280301

281302
@click.command()

0 commit comments

Comments
 (0)