[WIP] Subscriptions
All checks were successful
Test before pr merge / test-lint (pull_request) Successful in 6s

This commit is contained in:
2025-10-04 06:57:14 +02:00
parent e362b7fb61
commit cdb5e4ff89
21 changed files with 254 additions and 52 deletions

View File

@@ -1,8 +1,10 @@
from starlette.responses import JSONResponse
from api.src.queries.cities import CityGraphType, CityFilter, CitySort
from api.src.queries.hello import UserGraphType#, UserFilter, UserSort, UserGraphType
from api.src.queries.user import UserFilter, UserSort
from cpl.dependency.event_bus import EventBusABC
from cpl.graphql.event_bus.memory import InMemoryEventBus
from queries.cities import CityGraphType, CityFilter, CitySort
from queries.hello import UserGraphType # , UserFilter, UserSort, UserGraphType
from queries.user import UserFilter, UserSort
from cpl.api.api_module import ApiModule
from cpl.application.application_builder import ApplicationBuilder
from cpl.auth.schema import User, Role
@@ -17,7 +19,7 @@ from cpl.graphql.graphql_module import GraphQLModule
from model.author_dao import AuthorDao
from model.author_query import AuthorGraphType, AuthorFilter, AuthorSort
from model.post_dao import PostDao
from model.post_query import PostFilter, PostSort, PostGraphType, PostMutation
from model.post_query import PostFilter, PostSort, PostGraphType, PostMutation, PostSubscription
from permissions import PostPermissions
from queries.hello import HelloQuery
from scoped_service import ScopedService
@@ -41,6 +43,7 @@ def main():
.add_module(GraphQLModule)
.add_module(GraphQLAuthModule)
.add_scoped(ScopedService)
.add_singleton(EventBusABC, InMemoryEventBus)
.add_cache(User)
.add_cache(Role)
.add_transient(CityGraphType)
@@ -66,6 +69,7 @@ def main():
.add_transient(PostFilter)
.add_transient(PostSort)
.add_transient(PostMutation)
.add_transient(PostSubscription)
)
app = builder.build()
@@ -96,6 +100,8 @@ def main():
schema.mutation.with_mutation("post", PostMutation).with_public()
schema.subscription.with_subscription("post", PostSubscription)
app.with_auth_root_queries(True)
app.with_auth_root_mutations(True)

View File

@@ -1,3 +1,4 @@
from cpl.dependency.event_bus import EventBusABC
from cpl.graphql.query_context import QueryContext
from cpl.graphql.schema.db_model_graph_type import DbModelGraphType
from cpl.graphql.schema.filter.db_model_filter import DbModelFilter
@@ -5,6 +6,7 @@ from cpl.graphql.schema.input import Input
from cpl.graphql.schema.mutation import Mutation
from cpl.graphql.schema.sort.sort import Sort
from cpl.graphql.schema.sort.sort_order import SortOrder
from cpl.graphql.schema.subscription import Subscription
from model.author_dao import AuthorDao
from model.author_query import AuthorGraphType, AuthorFilter
from model.post import Post
@@ -19,6 +21,7 @@ class PostFilter(DbModelFilter[Post]):
self.string_field("title")
self.string_field("content")
class PostSort(Sort[Post]):
def __init__(self):
Sort.__init__(self)
@@ -26,6 +29,7 @@ class PostSort(Sort[Post]):
self.field("title", SortOrder)
self.field("content", SortOrder)
class PostGraphType(DbModelGraphType[Post]):
def __init__(self, authors: AuthorDao):
@@ -42,7 +46,7 @@ class PostGraphType(DbModelGraphType[Post]):
def r_name(ctx: QueryContext):
return ctx.user.username == "admin"
self.object_field("author", AuthorGraphType, resolver=_a).with_public(True)# .with_require_any([], [r_name]))
self.object_field("author", AuthorGraphType, resolver=_a).with_public(True) # .with_require_any([], [r_name]))
self.string_field(
"title",
resolver=lambda root: root.title,
@@ -64,6 +68,7 @@ class PostCreateInput(Input[Post]):
self.string_field("content").with_required()
self.int_field("author_id").with_required()
class PostUpdateInput(Input[Post]):
title: str
content: str
@@ -75,13 +80,31 @@ class PostUpdateInput(Input[Post]):
self.string_field("title").with_required(False)
self.string_field("content").with_required(False)
class PostSubscription(Subscription):
def __init__(self, bus: EventBusABC):
Subscription.__init__(self)
self._bus = bus
async def post_changed():
async for event in await self._bus.subscribe("postChange"):
print("Event:", event, type(event))
yield event
def selector(event: Post, info) -> bool:
return True
self.subscription_field("postChange", PostGraphType, post_changed, selector)
class PostMutation(Mutation):
def __init__(self, posts: PostDao, authors: AuthorDao):
def __init__(self, posts: PostDao, authors: AuthorDao, bus: EventBusABC):
Mutation.__init__(self)
self._posts = posts
self._authors = authors
self._bus = bus
self.field("create", int, resolver=self.create_post).with_public().with_required().with_argument(
"input",
@@ -112,6 +135,7 @@ class PostMutation(Mutation):
post.content = input.content if input.content is not None else post.content
await self._posts.update(post)
await self._bus.publish("postChange", post)
return True
async def delete_post(self, id: int) -> bool:
@@ -127,4 +151,3 @@ class PostMutation(Mutation):
return False
await self._posts.restore(post)
return True

View File

@@ -1,5 +1,5 @@
from api.src.queries.cities import CityFilter, CitySort, CityGraphType, City
from api.src.queries.user import User, UserFilter, UserSort, UserGraphType
from queries.cities import CityFilter, CitySort, CityGraphType, City
from queries.user import User, UserFilter, UserSort, UserGraphType
from cpl.api.middleware.request import get_request
from cpl.auth.schema import UserDao, User
from cpl.graphql.schema.filter.filter import Filter
@@ -38,6 +38,7 @@ cities = [City(i, f"City {i}") for i in range(1, 101)]
# resolver=lambda root: root.username,
# )
class HelloQuery(Query):
def __init__(self):
Query.__init__(self)