langflow icon indicating copy to clipboard operation
langflow copied to clipboard

Bugs in RedisCache Init and Serialization

Open dhlidongming opened this issue 1 year ago • 1 comments

Bug Description

I've encountered two bugs while using RedisCache:

  1. The is_connected method: https://github.com/langflow-ai/langflow/blob/a97c29fb398a04b2e23a889627a5b30102782f3d/src/backend/base/langflow/services/cache/service.py#L222-L227 is called within an asynchronous method: https://github.com/langflow-ai/langflow/blob/a97c29fb398a04b2e23a889627a5b30102782f3d/src/backend/base/langflow/main.py#L105 When using asyncio.run, it raises the error: RuntimeError: asyncio.run() cannot be called from a running event loop.

  2. Serialization error occurs for graphs and many outputs that are not of Message and Data component types, raising TypeError or PicklingError: https://github.com/langflow-ai/langflow/blob/a97c29fb398a04b2e23a889627a5b30102782f3d/src/backend/base/langflow/services/cache/service.py#L241-L250

Reproduction

  1. Set Environment Variable:

    • Configure the environment variable LANGFLOW_CACHE_TYPE to redis.
  2. Start Application:

    • Launch the application. This results in an error during asyncio.run, specifically:
      RuntimeError: asyncio.run() cannot be called from a running event loop.
      
  3. Modify Code:

    • Remove or comment out the is_connected method call.
    • Execute any flow within the application. This leads to the following error:
      TypeError: RedisCache only accepts values that can be pickled.
      

Expected behavior

  1. The RedisCache should initialize without raising errors.

  2. The RedisCache should accept values without raising serialization errors, ensuring compatibility with various output types.

Who can help?

@italojohnny

Operating System

MacOS

Langflow Version

1.1.1

Python Version

None

Screenshot

No response

Flow File

No response

dhlidongming avatar Dec 17 '24 11:12 dhlidongming

To address the issues with the RedisCache in Langflow version 1.1.1, you can make the following changes:

  1. Fixing the RuntimeError in is_connected: Avoid using asyncio.run() within an already running event loop. Instead, check if the event loop is running and use create_task or run_until_complete accordingly. Here's a modified version of the is_connected method:

    def is_connected(self) -> bool:
        """Check if the Redis client is connected."""
        import redis
        try:
            loop = asyncio.get_event_loop()
            if loop.is_running():
                # If the loop is already running, use create_task
                task = loop.create_task(self._client.ping())
                loop.run_until_complete(task)
            else:
                asyncio.run(self._client.ping())
        except redis.exceptions.ConnectionError:
            logger.exception("RedisCache could not connect to the Redis server")
            return False
        return True
    
  2. Handling Serialization Issues: Ensure that only picklable objects are cached. Add a check before attempting to pickle the object in the set method:

    @override
    async def set(self, key, value, lock=None) -> None:
        try:
            # Check if the value can be pickled
            pickle.dumps(value)
            if pickled := pickle.dumps(value):
                result = await self._client.setex(str(key), self.expiration_time, pickled)
                if not result:
                    msg = "RedisCache could not set the value."
                    raise ValueError(msg)
        except (TypeError, pickle.PicklingError) as exc:
            msg = "RedisCache only accepts values that can be pickled."
            raise TypeError(msg) from exc
    

These changes should help resolve the RuntimeError and serialization issues you are encountering with the RedisCache on MacOS [1].

To continue talking to Dosu, mention @dosu.


Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Other

dosubot[bot] avatar Dec 17 '24 11:12 dosubot[bot]

I also saw this error with this simple setup:

  • run docker langflow v1.1.1
  • set LANGFLOW_REDIS_HOST or LANGFLOW_REDIS_URL
  • set LANGFLOW_CACHE_TYPE to "redis"

Basically, when cache type is set to redis, the following error shows: RuntimeError: asyncio.run() cannot be called from a running event loop.

orinciog avatar Jan 28 '25 11:01 orinciog

Experiencing this in 1.1.3 as well. Although from looking at the codebase, this is going to be present in all versions. No idea how this was ever working in the first place.

GarrettGeorge avatar Mar 03 '25 18:03 GarrettGeorge