Search code examples
pythongoogle-apigoogle-cloud-pubsubfastapigoogle-classroom

Is there a way to listen for updates on multiple Google Classroom Courses using Pub Sub?


Goal

Trigger a function which updates Cloud Firestore when a student completes assignments or assignments are added for any course.

Problem

The official docs state that a feed for CourseWorkChangesInfo requires a courseId, and I would like to avoid having a registration and subscription for each course, each running on its own thread.

What I Have

I have managed to get a registration to one course working:

def registration_body():
    return {  # An instruction to Classroom to send notifications from the `feed` to the
        # provided destination.
        "feed": {  # Information about a `Feed` with a `feed_type` of `COURSE_WORK_CHANGES`.
            "feedType": "COURSE_WORK_CHANGES",  # Information about a `Feed` with a `feed_type` of `COURSE_WORK_CHANGES`.
            "courseWorkChangesInfo": { 
                # This field must be specified if `feed_type` is `COURSE_WORK_CHANGES`.
                "courseId": "xxxxxxxxxxxx",  # The `course_id` of the course to subscribe to work changes for.
            },
        },
        "cloudPubsubTopic": {
            "topicName": "projects/xxxxx/topics/gcr-course",  # The `name` field of a Cloud Pub/Sub
        },
    }


def create_registration(service):
    """
    Creates a registration to the Google Classroom Service which will listen
    for updates on Google Classroom according to the requested body.
    Pub Sub will emit a payload to subscribers when a classroom upate occurs.

    Args:
        service (Google Classroom Service): Google Classroom Service as retrieved
        from the Google Aclassroom Service builder

    Returns:
        Registration: Google Classroom Registration
    """

    body = registration_body()
    try:
        registration = service.registrations().create(body=body).execute()
        print(f"Registration to Google CLassroom Created\n{registration}")
        return registration
    except Exception as e:
        print(e)
        raise

And am successfully able to subscribe to those updates alongside my FastAPI server:

def init_subscription():
    # [INIT PUBSUB SUBSCRIBER AND CALLBACKS]
    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(
        "x-student-portal", "gcr-course-sub"
    )
    future = subscriber.subscribe(subscription_path, callback)
    with subscriber:
        try:
            future.result()
        except TimeoutError:
            future.cancel()
            future.result()


def callback(message):
    print("message recieved")
    # do_stuff(message)
    print(message)
    message.ack()

The registration and subscription initialization:

@app.on_event("startup")
async def startup_event():
    global db
    global gc_api
    global gc_service
    global gc_registration
    global future
    global pub_sub_subscription_thread

    db = firestore.FirestoreDatabase()
    gc_service = get_service()
    gc_api = ClassroomApi(service=gc_service)
    gc_registration = publisher_client.create_registration(gc_service)

    pub_sub_subscription_thread = multiprocessing.Process(
        target=publisher_client.init_subscription
    )
    pub_sub_subscription_thread.start()

Conclusion

I would very much like to avoid running multiple threads while still being able to subscribe to changes in all my courses.

Any advice would be appreciated.


Solution

  • Answer:

    This is not possible.

    You cannot have a single registration to track course work changes for multiple courses, as you can see here:

    Types of feeds

    The Classroom API currently offers three types of feed:

    • Each domain has a roster changes for domain feed, which exposes notifications when students and teachers join and leave courses in that domain.
    • Each course has a roster changes for course feed, which exposes notifications when students and teachers join and leave courses in that course.
    • Each course has a course work changes for course feed, which exposes notifications when any course work or student submission objects are created or modified in that course.

    File a feature request:

    If you think this feature could be useful, I'd suggest you to file a feature request in Issue Tracker using this template.

    Reference: