in bedrock/contentful/management/commands/update_contentful.py [0:0]
def _queue_has_viable_messages(self) -> bool:
"""
When pages/entries change, Contentful uses a webhook to push a
message into a queue. Here, we get all enqueued messages and if ANY ONE
of them has an action of a 'go' type, we count that as enough and
we re-sync all of our Contentful content.
If we get a 'go' signal, we explicitly drain the queue rather than waste
network I/O on pointless checking. If we don't get a 'go' signal at all,
we still effectively have purged the queue, just iteratively.
What action types count as a 'go' signal?
* auto_save -> YES if using preview mode (ie on Dev/Stage)
* create -> NO, NEVER - not on Prod, Stage or Dev
* publish -> YES
* save -> YES if using preview mode
* unarchive -> YES
* archive -> YES (and we'll remove the page from bedrock's DB as well)
* unpublish -> YES (as above)
* delete -> YES (as above)
"""
poll_queue = True
may_purge_queue = False
viable_message_found = False
GO_ACTIONS = {
ACTION_ARCHIVE,
ACTION_PUBLISH,
ACTION_UNARCHIVE,
ACTION_UNPUBLISH,
ACTION_DELETE,
}
EXTRA_PREVIEW_API_GO_ACTIONS = {
# Sites that are using the preview API key (Dev and Stage) act upon
# two more state changes
ACTION_AUTO_SAVE,
ACTION_SAVE,
}
if settings.APP_NAME != "bedrock-prod":
# See settings.base.get_app_name()
GO_ACTIONS = GO_ACTIONS.union(EXTRA_PREVIEW_API_GO_ACTIONS)
if not settings.CONTENTFUL_NOTIFICATION_QUEUE_ACCESS_KEY_ID:
self.log(
"AWS SQS Credentials not configured for Contentful webhook",
)
# We don't want things to block/fail if we don't have SQS config.
# Instead, in this situation, it's better to just assume we got
# a 'go' signal and poll Contentful anyway.
return True
sqs = boto3.resource(
"sqs",
region_name=settings.CONTENTFUL_NOTIFICATION_QUEUE_REGION,
aws_access_key_id=settings.CONTENTFUL_NOTIFICATION_QUEUE_ACCESS_KEY_ID,
aws_secret_access_key=settings.CONTENTFUL_NOTIFICATION_QUEUE_SECRET_ACCESS_KEY,
)
queue = sqs.Queue(settings.CONTENTFUL_NOTIFICATION_QUEUE_URL)
while poll_queue:
msg_batch = queue.receive_messages(
WaitTimeSeconds=settings.CONTENTFUL_NOTIFICATION_QUEUE_WAIT_TIME,
MaxNumberOfMessages=MAX_MESSAGES_PER_QUEUE_POLL,
)
if len(msg_batch) == 0:
self.log("No messages in the queue")
break
for sqs_msg in msg_batch:
msg_body = sqs_msg.body
action = self._get_message_action(msg_body)
if action in GO_ACTIONS:
# we've found a viable one, so that's great. Drain down the queue and move on
viable_message_found = True
self.log(f"Got a viable message: {msg_body}")
may_purge_queue = True
poll_queue = False # no need to get more messages
break
else:
# Explicitly delete the message and move on to the next one.
# Note that we don't purge the entire queue even if all of the
# current messages are inviable, because we don't want the risk
# of a viable message being lost during the purge process.
sqs_msg.delete()
continue
if not viable_message_found:
self.log("No viable message found in queue")
if may_purge_queue:
self._purge_queue(queue)
return viable_message_found