Module: Telegram::Bot::Async

Included in:
Client
Defined in:
lib/telegram/bot/async.rb

Overview

Telegram clients can perform requests in async way with any job adapter (ActiveJob by default). Using Rails you don’t need any additional configuration. However you may want to enable async requests by default with ‘async: true` in `secrets.yml`.

telegram:
  bots:
    chat_async:
      token: secret
      async: true # enable async mode for client

Without Rails To start using async requests initialize client with ‘id` kwarg and make sure the client is accessible via `Teletgram.bots` in job worker. Or just use `Telegram.bots_config=` for configuration.

Being in async mode ‘#request` enqueues job to perform http request instead of performing it immediately. Async behavior is controlled with `#async=` writer and can be enabled/disabled for the block with `#async`:

client = Telegram::Bot::Client.new(**config, async: true)
client.send_message(message)
client.async(false) { client.send_message(other_one) }

‘#async=` sets global value for all threads, while `#async(val, &block)` is thread-safe.

It can be set with custom job class or classname. By default it defines job classes inherited from ApplicationJob, which can be accessed via ‘.default_async_job`. You can integrate it with any other job provider by defining a class with `.perform_later(bot_id, *args)` method. See Async::Job for implemetation.

Defined Under Namespace

Modules: ClassMethods, Job

Constant Summary collapse

MISSING_VALUE =

Used to track missing key in a hash in local variable.

Object.new.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



114
115
116
# File 'lib/telegram/bot/async.rb', line 114

def id
  @id
end

Class Method Details

.prepare_hash(hash) ⇒ Object

Transforms symbols to strings in hash values.



102
103
104
105
106
# File 'lib/telegram/bot/async.rb', line 102

def prepare_hash(hash)
  return hash unless hash.is_a?(Hash)
  hash = hash.dup
  hash.each { |key, val| hash[key] = val.to_s if val.is_a?(Symbol) }
end

.prepended(base) ⇒ Object



97
98
99
# File 'lib/telegram/bot/async.rb', line 97

def prepended(base)
  base.extend(ClassMethods)
end

.thread_storeObject

Thread-local hash to store async config for every client.



109
110
111
# File 'lib/telegram/bot/async.rb', line 109

def thread_store
  Thread.current[:telegram_bot_async] ||= {}
end

Instance Method Details

#async(val = true) ⇒ Object

Sets async value in a thread-safe way for the block. Uses ‘self.class.prepare_async_val` to prepare value.

If no block is given returns previously set value or the global one, set by #async=.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/telegram/bot/async.rb', line 133

def async(val = true) # rubocop:disable Style/OptionalBooleanParameter
  thread_key = object_id
  thread_store = Async.thread_store
  return thread_store.fetch(thread_key) { @async } unless block_given?
  begin
    old_val = thread_store.fetch(thread_key) { MISSING_VALUE }
    thread_store[thread_key] = self.class.prepare_async_val(val)
    yield
  ensure
    if old_val == MISSING_VALUE
      thread_store.delete(thread_key)
    else
      thread_store[thread_key] = old_val
    end
  end
end

#async=(val) ⇒ Object

Sets default async value for all threads. Uses ‘self.class.prepare_async_val` to prepare value.



124
125
126
# File 'lib/telegram/bot/async.rb', line 124

def async=(val)
  @async = self.class.prepare_async_val(val)
end

#initialize(id: nil, async: nil, **options) ⇒ Object



116
117
118
119
120
# File 'lib/telegram/bot/async.rb', line 116

def initialize(*, id: nil, async: nil, **options)
  @id = id
  self.async = async
  super
end

#request(*args) ⇒ Object

Uses job if #async is set.



151
152
153
154
155
156
# File 'lib/telegram/bot/async.rb', line 151

def request(*args)
  job_class = async
  return super unless job_class
  raise 'Can not enqueue job without client id' unless id
  job_class.perform_later(id.to_s, *self.class.prepare_async_args(*args))
end