Module: Telegram::Bot::Async

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


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

def id
  @id
end

Class Method Details

.prepare_hash(hash) ⇒ Object

Transforms symbols to strings in hash values.


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

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


95
96
97
# File 'lib/telegram/bot/async.rb', line 95

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

.thread_storeObject

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


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

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


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

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.


122
123
124
# File 'lib/telegram/bot/async.rb', line 122

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

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


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

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

#request(*args) ⇒ Object

Uses job if #async is set.


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

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