В рамках следующей итерации над демо-проектом Shrimp постарались закрыть несколько "косяков" самой первой, простейшей версии Shrimp-а. В частности, в простейшей версии Shrimp-а были возможны ситуации, когда пришедшие практически одновременно одинаковые запросы шли в параллельную обработку. Т.е., если мы получаем запрос "demo.jpg?op=resize&max=1024" и следом еще один такой же, то операция трансформации картинки demo.jpg к размеру 1024px могла быть запущена дважды.
Происходило это потому, что Shrimp проверял наличие уже трансформированной картинки в своем кэше. Если ее в кэше нет, то при наличии свободных worker-ов запрос сразу же шел в обработку. Получили запрос для demo.jpg, увидели, что в кэше результата нет, отдали на трансформацию. Результат трансформации еще не пришел, а у нас уже еще один запрос для demo.jpg. Поскольку трансформированной картинки в кэше, ожидаемо, нет, то отдаем запрос на обработку. И получаем, что одна и так же картинка трансформируется параллельно несколькими воркерами. Что не есть хорошо.
Понятное дело, что для самой первой, самой простейшей версии Shrimp-а не было смысла делать контроль уникальности запросов. Но вот добавить подобный контроль в последующих версиях нужно было. Работы тут не так много, а солидности демо-проекту добавляет :)
И вот при реализации контроля за уникальностью ждущих/обрабатывающихся запросов оказалось, что хорошо бы иметь такой контейнер, который, с одной стороны, выглядел бы как очередь, сохраняющая хронологический порядок добавления элементов. Это качество оказалось особенно важно для очереди ждущих запросов. Ведь нужно ограничивать время пребывания запросов в pending-queue, а для этого нужно периодически просматривать очередь начиная с самых старых элементов в ней.
С другой же стороны, нужно иметь возможность эффективно проверить наличие конкретного ключа в контейнере. И, сюда же, нужно иметь возможность изъять из очереди сразу все элементы с одинаковым ключом. Нужно это в случае, когда освободился worker и мы берем самый старый элемент из очереди. Но, если ключ этого элемента не уникален (т.е. есть более свежие запросы с тем же ключом), то оставлять в очереди другие аналогичные элементы нет смысла. Ведь когда картинка будет трансформирована, то ее можно будет отдать сразу всем этим запросам.