Skip to content

Introduce MessageQueue #537

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 15, 2017
Merged

Introduce MessageQueue #537

merged 5 commits into from
Mar 15, 2017

Conversation

thodnev
Copy link
Member

@thodnev thodnev commented Mar 2, 2017

This commit is 2nd step on bringing output messages throughput-limiting mechanisms to the lib.
I've briefly mentioned the ideas behind MessageQueue in dev chat before. Here are the main points of the commit:

  • New telegram.ext.messagequeue module, containing DelayQueue, MessageQueue classes and queuedmessage decorator;
  • DelayQueue is the core of throughput-limiting mechanism. It runs Promise callbacks, dispatched by queue in a thread, with respect to provided limits;
  • MessageQueue is a class, which embeds two instances of DelayQueue in sequential-interconnection way (one for group messages, another for all messages). The figure below illustrates how it works: flow chart
  • queuedmessage decorator is meant to be used with telegram.bot.Bot output conversation methods to make them accept additional kwargs. Messages are passed through MessageQueue depending on kwargs set;
  • telegram.ext.messagequeue module is properly documented for good usability;
  • Test of the core (DelayQueue) is added.

So, the next step in the process would be to couple MessageQueue with telegram.bot.Bot in best way ;)

@jh0ker
Copy link
Member

jh0ker commented Mar 2, 2017

Fucking awesome!

@thodnev thodnev requested a review from jh0ker March 2, 2017 23:07
@thodnev thodnev self-assigned this Mar 2, 2017
Copy link
Member

@jh0ker jh0ker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty solid to me already, however there are a few things I'd like to see cleared up before we can merge.

There are also a few mentions of dispatcher or dispatching which might be confused with telegram.ext.Dispatcher. Can those be replaced with something more clearly referring to MessageQueue without changing the meaning?

@@ -0,0 +1,309 @@
'''A throughput-limiting message dispatcher for Telegram bots'''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the default header we have in all source files

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

queue (:obj:`queue.Queue`, optional): used to pass callbacks to
thread.
Creates `queue.Queue` implicitly if not provided.
burst_limit (:obj:`int`, optional): numer of maximum callbacks to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: numer -> number

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

time_limit_ms (:obj:`int`, optional): defines width of time-window
used when each dispatching limit is calculated.
Defaults to 1000.
exc_route (:obj:`callable`, optional): a callable, accepting 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were relying on the promise here? Although it might still make sense to have both... just wondering if this is intentional.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Promises are used, but DelayQueue is left generic because it may be useful outside of the throughput-limiting scope

queued (:obj:`bool`, optional): if set to ``True``, the `MessageQueue`
is used to dispatch output messages.
Defaults to `self._is_queued_out`.
isgroup (:obj:`bool`, optional): if set to ``True``, the message is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could at least guess this by using the chat id (negative chat_id usually means it's a group). I know it's an implementation detail, but I'd still consider it a sane default in case this is not specified.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rejected. An accurate approach (a cached chat_id:type mapping) would be introduced further


@functools.wraps(method)
def wrapped(self, *args, **kwargs):
queued = kwargs.pop('queued', self._is_queued_out)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to make sure I understand this correctly, _is_queued_out will be an attribute of telegram.Bot? In that case, I'd prefer a name that includes the word default, like _queue_messages_default (or maybe something more concise?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Changed to _is_messages_queued_default. In my opinion, is should be left because it's common practice if attribute or variable is boolean

if len(times) >= self.burst_limit: # if throughput limit was hit
time.sleep(times[1] - t_delta)
# finally dispatch one
try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment about promises earlier: item would be a telegram.util.promise.Promise object, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

item is a tuple of form (func, args, kwargs) which becomes (promise, (), {}) and (delayqueue.__call__, (promise, ), {}) for corresponding processors

@jh0ker
Copy link
Member

jh0ker commented Mar 15, 2017

Travis shows errors with yapf, did you install the pre-commit hook? If you did, and it shows as passing for you, I can try applying the changes manually.

@thodnev
Copy link
Member Author

thodnev commented Mar 15, 2017

As it may be seen, Travis shows yapf error only on Python 3.5.
Yes, I've used pre-commit hooks, done the 'make yapf' check and also checked coding style with flake8 by hand.
Seems that it's error of build scripts seen on 3.5 only (a Heisenbug ?? cause I see no realistic reasons why it occurs only on this ver)

@jh0ker
Copy link
Member

jh0ker commented Mar 15, 2017

@thodnev We only run pre-commit hooks on python3.5 build, so we can save some time and easily see if the tests fail or if it's only the hooks that fail.

@jh0ker jh0ker merged commit 22142e7 into master Mar 15, 2017
@thodnev thodnev deleted the messagequeue branch March 15, 2017 23:39
@github-actions github-actions bot locked and limited conversation to collaborators Aug 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy