Синатра: распространение событий
Я работаю над небольшим приложением. Отправив задачу, пользователь может получать серию сообщений о состоянии - таким образом, можно понять, была ли производительность успешной или нет. Это может быть реализовано с подпиской на события SSE и JS. Проблема в распределении событий и изоляции переменных - я никогда не работал с несколькими арендаторами.
Каждый пользователь должен работать со своим экземпляром приложения. Каждый пользователь должен получать свои собственные события.
Я знаю, как реализовать механизм аутентификации и как предоставить каждой задаче уникальный идентификатор, но как мне реализовать мультитенантность в приложении Sinatra? Есть много драгоценных камней и рецептов, но все они написаны для RoR.
Мое приложение обеспечивает обработку факсов Asterisk. Он состоит из двух частей: первая - обработчики маршрутов Синатры, вторая - бэкэнд-процесс - он прослушивает события Asterisk (AMI), а также обеспечивает отправку новой задачи.
Как говорят люди, все еще трудно понять, что должно делать мое приложение, я опишу это шаг за шагом.
- Пользователь подписывается.
- Пользователь отправляет задачу телефонии (например, факс). Это должен быть асинхронный процесс, потому что вы никогда не знаете, что произойдет: может быть занято, ответ может произойти на 5-й, 9-й секунде... и так далее.
- Таким образом, во время этого процесса пользователь получает сообщения, описывающие происходящее (наш фоновый процесс связывается с сервером телефонии).
- Однако в этот самый момент другой пользователь пользователя входит в систему и отправляет свое собственное задание. Оба пользователя видят свои частные потоки событий.
Но этого не происходит: пользователи видят беспорядок двух потоков событий. Это моя проблема.
На самом деле моя задача аналогична реализации чата с той разницей, что люди не должны разговаривать друг с другом. Предполагается, что они "общаются" с фоновым процессом через сервер. Каждый может сказать "Hello", сервер перенаправляет "Hello" в фоновый процесс, а затем возвращает из фонового процесса частный поток ответов владельцу, это происходит асинхронно. В чате вы можете сказать "Привет" другому приятелю, вы никогда не знаете, когда получите ответ, но сервер знает, что этот ответ ваш, и вы получите свой личный ответ.
Вот фрагменты:
class FaxServer < Sinatra::Base
...
post '/run' do
settings.backend_process.async.run(param1, param2)
end
...
end
class MyBackendProcess
def run(number, file)
if File.exist?(file) then
change_status("Calling attempt, please wait...")
$stream.async.send_action ...
end
...
def handle_event(event)
case
when event.name === "Newchannel"
change_status("New channel is created")
...
end
end
class StatusSender
include Celluloid
include Celluloid::Notifications
def send_status(message)
publish("status_event", "#{Time.now.strftime('%R:%S')} : #{message}")
end
end
class StatusObserver
include Celluloid
include Celluloid::Notifications
def initialize(server)
@server = server
subscribe "status_event", :status_event
end
def status_event(*args)
@server.settings.connections.each { |out| out << "event: #{args[0].to_s}\ndata: #{args[1]}\n\n" }
end
end
Заранее спасибо.