示例#1
0
def subscribe_fields(exe_context, parent_type, source_value, fields):
    exe_context = SubscriberExecutionContext(exe_context)

    def on_error(error):
        exe_context.report_error(error)

    def map_result(data):
        print("MAP RESULT:", data)
        if exe_context.errors:
            result = ExecutionResult(data=data, errors=exe_context.errors)
        else:
            result = ExecutionResult(data=data)
        exe_context.reset()
        return result

    # def catch_error(error):
    #     print("CATCH ERROR:", error)
    #     exe_context.errors.append(error)
    #     return None

    assert len(fields) == 1, "Can only subscribe one element at a time."
    for response_name, field_asts in fields.items():

        result = subscribe_field(exe_context, parent_type, source_value,
                                 field_asts)
        if result is Undefined:
            continue

        # Map observable results
        # error_obs = AsyncObservable.unit(None) | op.map(catch_error)
        obs = result | op.map(lambda x: {response_name: x}) | op.map(
            map_result)
        return obs
示例#2
0
async def test_forward_pipe_complex_pipe() -> None:
    xs = AsyncObservable.from_iterable([1, 2, 3])
    result = []

    def mapper(value) -> int:
        return value * 10

    async def predicate(value) -> bool:
        await asyncio.sleep(0.1)
        return value > 1

    async def long_running(value) -> AsyncObservable[int]:
        return AsyncObservable.from_iterable([value])

    ys = (xs
          | _.filter(predicate)
          | _.map(mapper)
          | _.flat_map(long_running)
          | _.to_async_iterable()
          )

    async for value in ys:
        result.append(value)

    assert result == [20, 30]
示例#3
0
def subscribe_field(exe_context, parent_type, source, field_asts):
    field_ast = field_asts[0]
    field_name = field_ast.name.value

    field_def = get_field_def(exe_context.schema, parent_type, field_name)
    if not field_def:
        return Undefined

    return_type = field_def.type
    resolve_fn = field_def.resolver or default_resolve_fn

    # We wrap the resolve_fn from the middleware
    resolve_fn_middleware = exe_context.get_field_resolver(resolve_fn)

    # Build a dict of arguments from the field.arguments AST, using the variables scope to
    # fulfill any variable references.
    args = exe_context.get_argument_values(field_def, field_ast)

    # The resolve function's optional third argument is a context value that
    # is provided to every resolve function within an execution. It is commonly
    # used to represent an authenticated user, or request-specific caches.
    context = exe_context.context_value

    # The resolve function's optional third argument is a collection of
    # information about the current execution state.
    info = ResolveInfo(field_name,
                       field_asts,
                       return_type,
                       parent_type,
                       schema=exe_context.schema,
                       fragments=exe_context.fragments,
                       root_value=exe_context.root_value,
                       operation=exe_context.operation,
                       variable_values=exe_context.variable_values,
                       context=context,
                       path=[field_name])

    executor = exe_context.executor
    if isinstance(executor, SyncExecutor):
        raise TypeError("Cannot use subscriptions with the SyncExecutor")

    result = resolve_or_error(resolve_fn_middleware, source, info, args,
                              executor)

    if isinstance(result, Exception):
        raise result

    if isinstance(result, Promise):
        result = executor.loop.run_until_complete(result)

    if not isinstance(result, AsyncObservable):
        raise GraphQLError(
            'Subscription must return an AsyncObservable. Received: {}'.format(
                repr(result)))

    return result | op.map(
        functools.partial(complete_value_catching_error, exe_context,
                          return_type, field_asts, info))
示例#4
0
async def test_pipe_map():
    xs = AsyncObservable.from_iterable([1, 2, 3])
    result = []

    def mapper(value):
        return value * 10

    ys = pipe(xs, _.map(mapper))

    async def asend(value):
        result.append(value)

    await run(ys, AsyncAnonymousObserver(asend))
    assert result == [10, 20, 30]
示例#5
0
async def test_forward_pipe_map() -> None:
    xs = AsyncObservable.from_iterable([1, 2, 3])
    result = []

    def mapper(value) -> int:
        return value * 10

    ys = xs | _.map(mapper)

    async def asend(value) -> None:
        result.append(value)

    await run(ys, AsyncAnonymousObserver(asend))
    assert result == [10, 20, 30]
示例#6
0
async def test_map_happy():
    xs = from_iterable([1, 2, 3])  # type: AsyncObservable[int]
    values = []

    async def asend(value):
        values.append(value)

    def mapper(value: int) -> int:
        return value * 10

    ys = xs | _.map(mapper)

    result = await run(ys, AsyncAnonymousObserver(asend))

    assert result == 30
    assert values == [10, 20, 30]
示例#7
0
async def test_forward_pipe_simple_pipe() -> None:
    xs = AsyncObservable.from_iterable([1, 2, 3])
    result = []

    def mapper(value) -> int:
        return value * 10

    async def predicate(value) -> bool:
        await asyncio.sleep(0.1)
        return value > 1

    ys = xs | _.filter(predicate) | _.map(mapper)

    async def asend(value) -> None:
        result.append(value)

    await run(ys, AsyncAnonymousObserver(asend))
    assert result == [20, 30]
示例#8
0
async def test_pipe_simple_pipe():
    xs = AsyncObservable.from_iterable([1, 2, 3])
    result = []

    def mapper(value):
        return value * 10

    async def predicate(value):
        await asyncio.sleep(0.1)
        return value > 1

    ys = pipe(xs, _.filter(predicate), _.map(mapper))

    async def asend(value):
        result.append(value)

    await run(ys, AsyncAnonymousObserver(asend))
    assert result == [20, 30]
示例#9
0
async def test_pipe_complex_pipe():
    xs = AsyncObservable.from_iterable([1, 2, 3])
    result = []

    def mapper(value):
        return value * 10

    async def predicate(value):
        await asyncio.sleep(0.1)
        return value > 1

    async def long_running(value):
        return AsyncObservable.from_iterable([value])

    ys = pipe(xs, _.filter(predicate), _.map(mapper), _.flat_map(long_running),
              _.to_async_iterable())

    async for value in ys:
        result.append(value)

    assert result == [20, 30]
示例#10
0
async def test_map_subscription_cancel():
    xs = AsyncStream()
    result = []
    sub = None

    def mapper(value):
        return value * 10

    ys = xs | _.map(mapper)

    async def asend(value):
        result.append(value)
        await sub.adispose()
        await asyncio.sleep(0)

    async with subscribe(ys, AsyncAnonymousObserver(asend)) as sub:

        await xs.asend(10)
        await asyncio.sleep(0)
        await xs.asend(20)

    assert result == [100]
示例#11
0
async def test_map_mapper_throws():
    xs = from_iterable([1])
    exception = None
    error = Exception("ex")

    async def asend(value):
        pass

    async def athrow(ex):
        nonlocal exception
        exception = ex

    def mapper(x):
        raise error

    ys = xs | _.map(mapper)

    try:
        await run(ys, AsyncAnonymousObserver(asend, athrow))
    except Exception as ex:
        assert ex == error

    assert exception == error
示例#12
0
 async def config_observable(self, cfg):
     return self.connection.start_with_and_changes(self.connection.db().table(cfg.name))\
         | Operators.map(lambda elem: {**elem, "config": cfg.name})\
示例#13
0
async def new_task_watch():
    db_host = os.environ.get('DATABASE_HOST')
    db_port = os.environ.get('DATABASE_PORT')

    conn = await connection(db_host, db_port)

    async def new_change(arg):
        try:
            row, webhooks = arg[0], arg[1]
            logger.debug(f"Dispatching row: {row}")

            event = row.get('event', 'undefined')
            hooks = webhooks.get(event, [])
            if len(hooks) > 0:
                webhook_future = asyncio.ensure_future(
                    service.webhook(hooks, row))

            try:
                handler = dispatch[event]
                await handler(conn, row)
            except KeyError:
                logger.debug(f"No handler for event type {row['event']}")
            except:
                logger.exception("Unknown exception in task processing")

            try:
                if len(hooks) > 0:
                    await webhook_future
            except:
                logger.exception("Unknown exception in webhook.")
        except:
            logger.exception("Unknown exception in task watch.")

    async def delayed(tasks):
        logger.debug(f"Got update in delayed tasks: {tasks}")

        if len(tasks) == 0:
            await asyncio.sleep(60)
            return

        task = next(iter(tasks))

        delta = datetime.fromtimestamp(
            task['at'], timezone.utc) - datetime.now(timezone.utc)
        await asyncio.sleep(delta.total_seconds())

        await conn.run(new_task(conn, task['event'], task['parameters']))
        await asyncio.shield(conn.run(remove_delayed(conn, task)))


    ready_tasks = conn.start_with_and_changes(conn.db().table('tasks') \
        .filter(lambda row: row['status'] == 'ready')
    )   | Operators.map(lambda c: c['new_val'])\
        | Operators.filter(lambda x: x is not None)

    webhooks = conn.changes_accumulate(conn.db().table('webhooks'))\
        | Operators.map(group_by("event"))

    return await asyncio.gather(
        subscribe(
            ready_tasks | with_latest_from(webhooks),
            AsyncAnonymousObserver(new_change)
        ),
        subscribe(
            conn.changes_accumulate(conn.db().table('delayed_tasks'))\
                | Operators.map(lambda tasks: sorted(tasks, key=lambda task: task['at'])),
            AsyncRepeatedlyCallWithLatest(delayed)
        )
    )