Skip to content

Commit 1fae2c1

Browse files
authored
Add sane deletion support (#36)
* Improves the dryrun support. * Adds deletion with proper limits. * Sets the cron to have a max delete of 5. Closes #34 Signed-off-by: Phil Dibowitz <phil@ipom.com>
1 parent 31d101b commit 1fae2c1

File tree

2 files changed

+116
-43
lines changed

2 files changed

+116
-43
lines changed

.github/workflows/sync.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
GUIDEBOOK_API_TOKEN: ${{ secrets.GUIDEBOOK_API_TOKEN }}
3434
GUIDEBOOK_JWT_TOKEN: ${{ secrets.GUIDEBOOK_JWT_TOKEN }}
3535
run: |
36-
CMD="python ./guidebook/sync_guidebook.py"
36+
CMD="python ./guidebook/sync_guidebook.py --max-deletes 5"
3737
3838
if [[ "${{ github.event.inputs.update }}" == "true" ]]; then
3939
CMD="$CMD --update"

guidebook/sync_guidebook.py

Lines changed: 115 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,11 @@ class GuideBook:
163163

164164
REGIONED_MAP = "Pasadena-Convention-Center-Map-1000-72-fs8"
165165

166-
def __init__(self, logger, update, dryrun, key, x_key=None):
166+
def __init__(self, logger, update, dryrun, max_deletes, key, x_key=None):
167167
self.logger = logger
168168
self.update = update
169169
self.dryrun = dryrun
170+
self.max_deletes = max_deletes
170171
self.headers = {"Authorization": "JWT " + key}
171172
self.guide = self.get_guide()
172173
self.tracks = self.get_things("tracks")
@@ -176,6 +177,7 @@ def __init__(self, logger, update, dryrun, key, x_key=None):
176177
session["import_id"]: session for session in self.sessions.values()
177178
}
178179
self.x_rooms = []
180+
self.nids_to_delete = []
179181

180182
if x_key:
181183
self.x_headers = {"Authorization": "JWT " + x_key}
@@ -262,15 +264,17 @@ def add_thing(self, thing, name, data, update, tid):
262264
functions that know how to build the data and use it.
263265
"""
264266
verb = "Updating" if update else "Adding"
265-
self.logger.info("%s %s '%s' to Guidebook" % (verb, thing, name))
266-
self.logger.debug("Data: %s" % data)
267-
headers = self.headers if not thing.startswith("x-") else self.x_headers
268267
if self.dryrun:
269268
self.logger.info(
270-
"[DRYRUN] Would have %s %s '%s' to Guidebook"
269+
"[DRYRUN] Would have: %s %s '%s' to Guidebook"
271270
% (verb, thing, name)
272271
)
273272
return
273+
274+
self.logger.info("%s %s '%s' to Guidebook" % (verb, thing, name))
275+
self.logger.debug("Data: %s" % data)
276+
headers = self.headers if not thing.startswith("x-") else self.x_headers
277+
274278
if update:
275279
response = requests.patch(
276280
self.URLS[thing] + "%d/" % tid, data=data, headers=headers
@@ -483,10 +487,20 @@ def setup_sessions(self, sessions_by_name, sessions_by_nid):
483487
self.add_session(session, update, sid, True)
484488
else:
485489
self.logger.warning(
486-
"Session '%s' exists in Guidebook but not in our data. "
487-
"It will be left alone, but you may want to delete it.",
488-
name,
490+
"Session '%s' exists in Guidebook, but has no NID,"
491+
" and we cannot find the name in our data. Deleting it."
492+
% name,
493+
)
494+
self.delete_session(info)
495+
else:
496+
nid = info["import_id"]
497+
if nid not in sessions_by_nid.keys():
498+
self.logger.warning(
499+
"Session '%s' with NID %s exists in Guidebook, but we"
500+
" cannot find it in our data. Adding it to the delete"
501+
" list." % (name, nid)
489502
)
503+
self.nids_to_delete.append(nid)
490504

491505
# now loop through pass in sessions, and add/update as needed
492506
for nid, session in sessions_by_nid.items():
@@ -502,58 +516,111 @@ def setup_sessions(self, sessions_by_name, sessions_by_nid):
502516
sid = self.sessions_by_nid[nid]["id"]
503517
self.add_session(session, update, sid)
504518

519+
# Clean up sessions that should be deleted
520+
num_deletes = len(self.nids_to_delete)
521+
if num_deletes == 0:
522+
return
523+
524+
if num_deletes > self.max_deletes:
525+
self.logger.warning(
526+
"Number of sessions to delete (%d) exceeds the max threshold"
527+
" (%d). Not deleting any sessions.",
528+
num_deletes,
529+
self.max_deletes,
530+
)
531+
else:
532+
self.logger.warning(
533+
"Deleting %d sessions that are no longer in our data",
534+
num_deletes,
535+
)
536+
for nid in self.nids_to_delete:
537+
session = self.sessions_by_nid[nid]
538+
self.delete_session(session)
539+
540+
def delete_session(self, session):
541+
if self.dryrun:
542+
self.logger.info(
543+
"[DRYRUN] Would have deleted session '%s' from Guidebook"
544+
% session["name"]
545+
)
546+
return
547+
548+
self.logger.debug(
549+
"Deleting session %d [%s]" % (session["id"], session["name"])
550+
)
551+
response = requests.delete(
552+
self.URLS["sessions"] + "%d/" % session["id"],
553+
headers=self.headers,
554+
)
555+
self.logger.debug("Got %d" % response.status_code)
556+
if not (response.status_code >= 200 and response.status_code < 300):
557+
self.logger.error("Failed to delete")
558+
self.logger.error("RESPONSE: %s" % response.json())
559+
sys.exit(1)
560+
505561
def delete_sessions(self):
506562
self.logger.warning("Deleting all sessions")
507563
for session in self.sessions.values():
508-
self.logger.debug(
509-
"Deleting session %d [%s]" % (session["id"], session["name"])
510-
)
511-
response = requests.delete(
512-
self.URLS["sessions"] + "%d/" % session["id"],
513-
headers=self.headers,
564+
self.delete_session(session)
565+
566+
def delete_track(self, track):
567+
if self.dryrun:
568+
self.logger.info(
569+
"[DRYRUN] Would have deleted track '%s' from Guidebook"
570+
% track["name"]
514571
)
515-
self.logger.debug("Got %d" % response.status_code)
516-
if not (response.status_code >= 200 and response.status_code < 300):
517-
self.logger.error("Failed to delete")
518-
self.logger.error("RESPONSE: %s" % response.json())
519-
sys.exit(1)
572+
return
573+
574+
self.logger.debug(
575+
"Deleting track %d [%s]" % (track["id"], track["name"])
576+
)
577+
response = requests.delete(
578+
self.URLS["tracks"] + "%d/" % track["id"],
579+
headers=self.headers,
580+
)
581+
if response.status_code != 204:
582+
self.logger.error("Failed to delete")
583+
self.logger.error("RESPONSE: %s" % response.json())
584+
sys.exit(1)
520585

521586
def delete_tracks(self):
522587
self.logger.warning("Deleting all tracks")
523588
for track in self.tracks.values():
524-
self.logger.debug(
525-
"Deleting track %d [%s]" % (track["id"], track["name"])
526-
)
527-
response = requests.delete(
528-
self.URLS["tracks"] + "%d/" % track["id"],
529-
headers=self.headers,
589+
self.delete_track(track)
590+
591+
def delete_room(self, room):
592+
if self.dryrun:
593+
self.logger.info(
594+
"[DRYRUN] Would have deleted room '%s' from Guidebook"
595+
% room["name"]
530596
)
531-
if response.status_code != 204:
532-
self.logger.error("Failed to delete")
533-
self.logger.error("RESPONSE: %s" % response.json())
534-
sys.exit(1)
597+
return
598+
599+
self.logger.debug("Deleting room %d [%s]" % (room["id"], room["name"]))
600+
response = requests.delete(
601+
self.URLS["rooms"] + "%d/" % room["id"],
602+
headers=self.headers,
603+
)
604+
if response.status_code != 204:
605+
self.logger.error("Failed to delete")
606+
self.logger.error("RESPONSE: %s" % response.json())
607+
sys.exit(1)
535608

536609
def delete_rooms(self):
537610
self.logger.warning("Deleting all rooms")
538611
for room in self.rooms.values():
539-
self.logger.debug(
540-
"Deleting room %d [%s]" % (room["id"], room["name"])
541-
)
542-
response = requests.delete(
543-
self.URLS["rooms"] + "%d/" % room["id"],
544-
headers=self.headers,
545-
)
546-
if response.status_code != 204:
547-
self.logger.error("Failed to delete")
548-
self.logger.error("RESPONSE: %s" % response.json())
549-
sys.exit(1)
612+
self.delete_room(room)
550613

551614
def delete_all(self):
552615
self.delete_sessions()
553616
self.delete_tracks()
554617
self.delete_rooms()
555618

556619
def publish_updates(self):
620+
if self.dryrun:
621+
self.logger.info("[DRYRUN] Would have published pending updates.")
622+
return
623+
557624
self.logger.info("Publishing changes")
558625
response = requests.post(
559626
self.URLS["publish"].format(guide=self.guide),
@@ -627,7 +694,13 @@ def get_tokens(logger):
627694
default=False,
628695
help="Don't actually make any changes to Guidebook.",
629696
)
630-
def main(debug, update, delete_all, feed, dryrun):
697+
@click.option(
698+
"--max-deletes",
699+
default=0,
700+
help="Max number of sessions to delete when syncing. Zero will not"
701+
" delete any sessions. Ignored if --delete-all is used.",
702+
)
703+
def main(debug, update, delete_all, feed, dryrun, max_deletes):
631704
"""
632705
Sync the schedule data from our website to Guidebook.
633706
@@ -663,7 +736,7 @@ def main(debug, update, delete_all, feed, dryrun):
663736
else:
664737
ourdata = OurJSON(feed, logger)
665738

666-
ourguide = GuideBook(logger, update, dryrun, key, x_key=x_key)
739+
ourguide = GuideBook(logger, update, dryrun, max_deletes, key, x_key=x_key)
667740
if delete_all:
668741
ourguide.delete_all()
669742
else:

0 commit comments

Comments
 (0)