taskiq icon indicating copy to clipboard operation
taskiq copied to clipboard

There is no way of sending a task with arbitrary types

Open Suoslex opened this issue 8 months ago • 4 comments

So I tried to use PickleSerializer. But it raises SendTaskError without message, which is not quite informative, by the way, so I needed to debug. And turned out formatter tries to dump a message beforehand, and raises PydanticSerializationError ("Unable to serialize unknown type: <my_class>"). So I tried to create my own simple PickleFormatter:

class PickleFormatter(TaskiqFormatter):
    def dumps(self, message: TaskiqMessage) -> BrokerMessage:
        return BrokerMessage(
            task_id=message.task_id,
            task_name=message.task_name,
            message=pickle.dumps(message),
            labels=message.labels,
        )

    def loads(self, message: bytes) -> TaskiqMessage:
        return pickle.loads(message)

And it sends a task, but then a worker raises pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for <my_class>.

Any workarounds for that?

Suoslex avatar Apr 08 '25 10:04 Suoslex

Can you please share a stacktrace?

s3rius avatar Apr 08 '25 11:04 s3rius

stacktrace

Yes, sure. What case you want me to send? With my PickleFormatter?

Suoslex avatar Apr 08 '25 11:04 Suoslex

Can you please share a stacktrace?

UPDATE: Turned out it works fine if I don't define a type annotation for the variable in the function definition. I think it's something associated with dependencies (I use Depends).

For example, it won't work:

async def task(my_object: MyClass, dependency: MyDependency = Depends()):
    ...

But this one does:

async def task(my_object, dependency: MyDependency = Depends()):
    ...

Traceback:

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/pydantic/type_adapter.py", line 271, in _init_core_attrs
    self.core_schema = _getattr_no_parents(self._type, '__pydantic_core_schema__')
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pydantic/type_adapter.py", line 55, in _getattr_no_parents
    raise AttributeError(attribute)
AttributeError: __pydantic_core_schema__

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/taskiq/receiver/receiver.py", line 148, in callback
    result = await self.run_task(
             ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/taskiq/receiver/receiver.py", line 218, in run_task
    parse_params(signature, self.task_hints.get(message.task_name) or {}, message)
  File "/usr/local/lib/python3.11/site-packages/taskiq/receiver/params_parser.py", line 87, in parse_params
    message.kwargs[param_name] = parse_obj_as(annot, value)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/taskiq/compat.py", line 22, in parse_obj_as
    return create_type_adapter(annot).validate_python(obj)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/taskiq/compat.py", line 19, in create_type_adapter
    return pydantic.TypeAdapter(annot)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pydantic/type_adapter.py", line 228, in __init__
    self._init_core_attrs(
  File "/usr/local/lib/python3.11/site-packages/pydantic/type_adapter.py", line 290, in _init_core_attrs
    core_schema = schema_generator.generate_schema(self._type)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py", line 612, in generate_schema
    schema = self._generate_schema_inner(obj)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py", line 886, in _generate_schema_inner
    return self.match_type(obj)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py", line 997, in match_type
    return self._unknown_type_schema(obj)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py", line 515, in _unknown_type_schema
    raise PydanticSchemaGenerationError(
pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for <class 'module.MyClass'>. Set `arbitrary_types_allowed=True` in the model_config to ignore this error or implement `__get_pydantic_core_schema__` on your type to fully support it.

If you got this error by calling handler(<some type>) within `__get_pydantic_core_schema__` then you likely need to call `handler.generate_schema(<some type>)` since we do not call `__get_pydantic_core_schema__` on `<some type>` otherwise to avoid infinite recursion.

Suoslex avatar Apr 08 '25 11:04 Suoslex

I guess it has something to do with pydantic in that case. Since we use model_validate to convert model back. I might play around to find a solution to your problem.

s3rius avatar Apr 08 '25 11:04 s3rius