- Notifications
You must be signed in to change notification settings - Fork5.9k
Shared/Distributed use of arbitrary_callback_data#5064
-
Hi! I was wondering if it's possible to make it so Right now I can see that bot loads callback_data on start, but if, for example, one of the updates is handled by another instance of the bot-server, then they won't be in sync => update will only process if it hits the same server that issued the message with the callback data. I don't see a clear cut way to request bot to update persistence for callback data after handling each update (request), perhaps I'm simply missing something. |
BetaWas this translation helpful?Give feedback.
All reactions
The Problem: Memory vs. Persistence
PTB's ArbitraryCallbackData system is designed primarily for single-instance bots.
Local Cache: It relies on an in-memory CallbackDataCache (RAM) to map the UUIDs (sent to Telegram) back to your Python objects.
Startup Only: The persistence layer (BasePersistence) loads callback data only on bot startup. It does not check the persistence layer dynamically when it receives an unknown UUID.
This is why Instance B cannot "see" the button created by Instance A—it loaded its cache at startup, and Instance A's new button was never synced to Instance B's RAM.
The Solutions
There are two ways to solve this. The first is the "Architecturally Correct" way for dis…
Replies: 1 comment
-
The Problem: Memory vs. Persistence Local Cache: It relies on an in-memory CallbackDataCache (RAM) to map the UUIDs (sent to Telegram) back to your Python objects. Startup Only: The persistence layer (BasePersistence) loads callback data only on bot startup. It does not check the persistence layer dynamically when it receives an unknown UUID. This is why Instance B cannot "see" the button created by Instance A—it loaded its cache at startup, and Instance A's new button was never synced to Instance B's RAM. The Solutions Solution 1: The "Stateless" Pattern (Recommended) Generate an ID: When sending a button, generate a unique ID (e.g., order_id or a UUID) and save your data to Redis yourself. Send String Data: Set the button's callback_data to a string that includes this ID (e.g., "view_order:12345"). Fetch on Handle: In your CallbackQueryHandler, parse the ID and fetch the data from Redis. Why this works: Redis acts as the "Single Source of Truth." Both instances can read/write to it in real-time without needing local RAM synchronization. Python Instance A: Sending the buttonimport redis 1. Save complex data to Redis manuallyorder_id = "555" 2. Send standard string buttonbutton = InlineKeyboardButton("View Order", callback_data=f"view:{order_id}") Instance B: Handling the updateasync def button_handler(update, context): Solution 2: The "Persistence Hack" (Complex) Standard PTB does not support this out of the box. You would need to subclass CallbackDataCache or monkey-patch it. The Logic: Create a custom RedisCallbackDataCache. Override the process_callback_query method. If the UUID is not found in local RAM, attempt to fetch it from Redis before raising InvalidCallbackData. |
BetaWas this translation helpful?Give feedback.
All reactions
👍 1