Я пытаюсь отслеживать запросы к серверу и что-то делаю, когда данные будут готовы. У меня есть следующий код, который, кажется, работает, но мне интересно, есть ли лучший способ сделать это - в частности, мне кажется странным, что в будущем ниже я разыменую обещание внутри разыменования атома, при этом атом, возможно, изменится штат.
(def requests (atom {:a (promise) :b (promise)}))
(future @(:b @requests) (println "b is ready"))
(swap! requests assoc :c (promise))
(deliver (:b @requests) 100)
>> b is ready
Спасибо,





Атомы были разработаны для решения именно этой проблемы:
Internally, swap! reads the current value, applies the function to it, and attempts to compare-and-set! it in. Since another thread may have changed the value in the intervening time, it may have to retry, and does so in a spin loop.
Так что здесь вы в безопасности, пока два потока не используют один и тот же ключ для карты (: a: b: c).
Основная проблема, которую я вижу в этом подходе, заключается в том, что вы помещаете это обещание внутри атома, но если кто-нибудь действительно мутирует атом, чтобы содержать другое обещание, ваша программа сломается: наблюдатель будет ждать обещания, которое никто другой не имеет. ссылка на. Вместо этого я бы поместил обещание в некую неизменяемую структуру, разделяемую двумя частями кода, которые должны взаимодействовать.
Вы могли бы быть немного интереснее и использовать канал core.async вместо обещания, но если вам нужно передать только одно значение, обещание подойдет.
Как вы скоординированно назначите ключи всем запросам, которые когда-либо получит сервер? У вас есть как минимум два потока, работающих на этой карте, и все они должны каким-то образом согласовать, какой ключ соответствует какому запросу. И если карта никогда не сжимается, то она неограниченно растет по мере поступления новых запросов и нехватки памяти.
У меня есть один основной планировщик, который периодически отправляет запросы, причем ключи являются атомными номерами, последовательно увеличивающимися: только один поток добавляет на карту. Другие потоки доставляют обещания с карты. Моя проблема больше в том, что некоторые запросы выполняются дольше, чем другие, и мне нужно какое-то ожидание / обратный вызов, когда данные будут готовы. Что касается проблемы с памятью - это должно быть управляемо, с несколькими ~ 1000 запросами перед каждым перезапуском программы.
Спасибо, понимаете беспокойство. Но мне нужна какая-то изменчивая структура, поскольку запросы будут поступать (если я не создам для начала очень-очень длинную неизменяемую карту?). В моем случае карта будет только расти (добавляться новые запросы), никогда не меняться, так что, надеюсь, все в порядке.