Module: Telegram::Bot::Async

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

Overview

Telegram & Botan 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`. Botan client doesn’t inherit async setting from client and must be configured separately.

telegram:
  bots:
    chat_async:
      token: secret
      async: true # enable async mode for client
      botan: botan_token # in this way botan will not be async
      botan: # in this way - it's in async mode
        token: botan_token
        async: true

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 instead to perform http request instead of performing it directly. 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 for every client class, inherited from ApplicationRecord, 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.



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

def id
  @id
end

Class Method Details

.prepare_hash(hash) ⇒ Object

Transforms symbols to strings in hash values.



105
106
107
108
109
# File 'lib/telegram/bot/async.rb', line 105

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



100
101
102
# File 'lib/telegram/bot/async.rb', line 100

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

.thread_storeObject

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



112
113
114
# File 'lib/telegram/bot/async.rb', line 112

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=.



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

def async(val = true)
  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 MISSING_VALUE == old_val
      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.



127
128
129
# File 'lib/telegram/bot/async.rb', line 127

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

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



119
120
121
122
123
# File 'lib/telegram/bot/async.rb', line 119

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

#request(*args) ⇒ Object

Uses job if #async is set.



154
155
156
157
158
159
# File 'lib/telegram/bot/async.rb', line 154

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