Search code examples
pythongoogle-calendar-apigoogle-api-client

Error 404 when trying to insert an ACL to a calendar with Python client - works if I retry


Using Google Suite for Education.

I have an app that wants to:

  • Create a new calendar.
  • Add an ACL to such calendar, so the student role would be "reader".

Everything is run through a service account.

The calendar is created just fine, but inserting the ACL throws a 404 error (redacted for privacy):

<HttpError 404 when requesting https://www.googleapis.com/calendar/v3/calendars/MY_DOMAIN_long_string%40group.calendar.google.com/acl?alt=json returned "Not Found">

The function that tries to insert the ACL:

    def _create_calendar_acl(calendar_id, user, role='reader'):
        credentials = service_account.Credentials.from_service_account_file(
            CalendarAPI.module_path)
        scoped_credentials = credentials.with_scopes(
            ['https://www.googleapis.com/auth/calendar'])

        delegated_credentials = scoped_credentials.with_subject(
            'an_admin_email')

        calendar_api = googleapiclient.discovery.build('calendar',
                                                       'v3',
                                                       credentials=delegated_credentials)
        body = {'role': role,
                'scope': {'type': 'user',
                          'value': user}}

        answer = calendar_api.acl().insert(calendarId=calendar_id,
                                           body=body,
                                           ).execute()
        return answer

The most funny thing is, if I retry the operation a couple times, it finally succeeds. Hence, that's what my code does:

def create_student_schedule_calendar(email):
    MAX_RETRIES = 5
    # Get student information

    # Create calendar
    answer = Calendar.create_calendar('a.calendar.owner@mydomain',
                                      f'Student Name - schedule',
                                      timezone='Europe/Madrid')

    calendar_id = answer['id']

    counter = 0
    while counter < MAX_RETRIES:
        try:
            print('Try ' + str(counter + 1))
            _create_calendar_acl(calendar_id=calendar_id, user=email)  # This is where the 404 is thrown
            break
        except HttpError:  # this is where the 404 is caught
            counter += 1
            print('Wait ' + str(counter ** 2))
            time.sleep(counter ** 2)
            continue

    if counter == MAX_RETRIES:
        raise Exception(f'Exceeded retries to create ACL for {calendar_id}')

Anyway, it takes four tries (between 14 and 30 seconds) to succeed - and sometimes it expires.

Would it be possible that the recently created calendar is not immediately available for the API using it?


Solution

  • Propagation is often an issue with cloud-based services. Large-scale online service are distributed along a network of machines which in themselves have some level of latency - there is a discrete, non-zero amount of time that information takes to propagate along a network and update everywhere.

    All operations working after the first call which doesn't result in 404, is demonstrative of this process.

    Mitigation:

    I suggest if you're creating and editing in the same function call implementing some kind of wait/sleep for a moment to mitigate getting 404s. This can be done in python using the time library:

    import time
    # calendar creation code here
    time.sleep(2)
    # calendar edit code here