Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Shared/Distributed use of arbitrary_callback_data#5064

Discussion options

Hi! I was wondering if it's possible to make it socallback_data is available among multiple instances of a bot, for example by means of having some distributed cache (like Redis).

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.

You must be logged in to vote

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

Comment options

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 distributed systems, and the second is a "Workaround" if you absolutely must keep your current code structure.

Solution 1: The "Stateless" Pattern (Recommended)
Don't use ArbitraryCallbackData for distributed bots. Instead, use standard string callback_data and manage the state manually in Redis. This is 100% reliable across multiple instances.

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 button

import redis
r = redis.Redis(host='localhost', port=6379, db=0)

1. Save complex data to Redis manually

order_id = "555"
order_data = {"item": "Pizza", "price": 20}
r.set(f"order:{order_id}", json.dumps(order_data))

2. Send standard string button

button = InlineKeyboardButton("View Order", callback_data=f"view:{order_id}")
Python

Instance B: Handling the update

async def button_handler(update, context):
query = update.callback_query
action, order_id = query.data.split(":") # "view", "555"

# 3. Fetch from Redisdata_json = r.get(f"order:{order_id}")order_data = json.loads(data_json)await query.message.reply_text(f"Order: {order_data['item']}")

Solution 2: The "Persistence Hack" (Complex)
If you are deeply committed to using ArbitraryCallbackData (e.g., passing whole objects), you would need to force the bot to check Redis when it encounters a "cache miss" (an unknown UUID).

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.

You must be logged in to vote
0 replies
Answer selected bymakisukurisu
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
Q&A
Labels
None yet
2 participants
@makisukurisu@RoxyBasicNeedBot

[8]ページ先頭

©2009-2025 Movatter.jp