Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial payload #93

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Initial payload #93

wants to merge 1 commit into from

Conversation

AndreyMZ
Copy link

@AndreyMZ AndreyMZ commented Apr 12, 2022

This pull request adds two features:

  1. Per-operation context - allows sharing any data between different calls to Subscription.publish for the same subscription (and the same connection).
  2. Initial payload - allows sending an arbitrary "initial" response to a client as soon as it is subscribed (before any call to Subscription.broadcast).

I use them like so (in schema.py):

from __future__ import annotations

from typing import Optional

import channels_graphql_ws
import graphene
from channels_graphql_ws.dict_as_object import DictAsObject
from graphene import ResolveInfo

from .task import Task

class TaskLogChanged(channels_graphql_ws.Subscription):
    class Arguments:
        id = graphene.Argument(graphene.NonNull(graphene.ID))

    content = graphene.Field(graphene.NonNull(graphene.List(graphene.NonNull(graphene.String))))
    begin = graphene.Field(graphene.NonNull(graphene.Int))
    end = graphene.Field(graphene.NonNull(graphene.Int))

    Payload = type(None)

    initial_payload: Payload = None

    @staticmethod
    def subscribe(root: None, info: ResolveInfo, id: str) -> Optional[list[str]]:
        task = Task(id)
        return [task.uuid]

    @classmethod
    def trigger(cls, task: Task) -> None:
        cls.broadcast_sync(group=task.uuid, payload=None)
        
    @classmethod
    async def trigger_async(cls, task: Task) -> None:
        await cls.broadcast_async(group=task.uuid, payload=None)

    @staticmethod
    def publish(payload: None, info: ResolveInfo, id: str) -> Optional[TaskLogChanged]:
        assert isinstance(info.context, DictAsObject)
        try:
            saved_cursor = info.context['cursor']
        except KeyError:
            saved_cursor = 0 
        
        task = Task(id)
        content, new_cursor = task.get_log(saved_cursor)

        if new_cursor == saved_cursor:
            assert len(list(content)) == 0
            return None # Skip this publication.
        else:
            info.context['cursor'] = new_cursor
            return TaskLogChanged(content=content, begin=saved_cursor, end=new_cursor)

@fdev
Copy link

fdev commented May 28, 2022

@stmarkevich @sergey-komissarov @prokher is there something preventing this pull request from being merged? I'm eagerly waiting for the initial payload feature to become available. 🙏

@AndreyMZ
Copy link
Author

Per-operation context has been implemented in 1.0.0rc1.

@AndreyMZ
Copy link
Author

Fixes #63.

@AndreyMZ AndreyMZ changed the title Per-operation context + initial payload Initial payload Jun 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants