В Ruby on Rails, как я могу сохранять объекты в памяти между сеансами

Я пытаюсь создать что-то (в конечном счете, драгоценный камень, но теперь приложение), которое работает следующим образом.

Предположим, например, записи БД - это породы собаки. Там родительский класс собаки и дочерний класс для каждой породы. Фактические породы неизвестны до времени выполнения.

При запуске сервера он будет загружать записи из БД и создавать экземпляры классов на основе записей, например. У меня могут быть два гончих и пудель. Когда кто-то приходит на сервер, они могут захотеть получить доступ к одному из этих экземпляров.

Почему бы просто не создать экземпляр "на лету"? В моем случае "собаки" - это в основном классы, которые содержат алгоритм и данные. Алгоритм не изменяется, данные редко изменяются (порядка суток), но выполнение самого алгоритма, в котором используются как данные, так и некоторые динамические данные, передаваемые, например, временная метка, будут доступны несколько раз в секунду.

Было бы глупо воссоздать экземпляр объекта и каждый раз загружать данные, просто чтобы сделать запрос, только чтобы сделать это снова при следующем запросе (запросы не изменяют состояние объекта). Я бы создавал и уничтожал несколько объектов в секунду, когда мог просто повторно использовать один и тот же объект.

нет смысла держать его в сеансе, так как человеку, желающему пуделя, не нужно иметь информацию о биглях в ее объекте сеанса; он не имеет значения (и не масштабируется).

Как сохранить эти объекты в памяти? Я в основном хочу, чтобы таблица поиска содержала экземпляры. В Java я бы создал синглтон с некоторым типом hashmap или массива, который сидит в памяти. В rails я попробовал это, создав класс singleton в папке lib. Я думаю - я, возможно, не понимаю этого права, - что экземпляр (тот факт, что он синглтон спорный) теряется, когда сеанс исчезает.

Самый близкий ответ, который я нашел, был http://www.ruby-forum.com/topic/129372, который в основном помещает все в поля и методы класса. Почему-то это не кажется правильным.

ТИА!

Дополнение: Я прихожу из Java. В Java я просто создаю объект, который находится в куче или, может быть, в дереве JNDI, и по мере того, как появятся HTTP-запросы, они будут обрабатываться сервлетом или EJB или некоторым элементом для запроса, который затем может получить доступ к постоянному объекту. Я не могу найти эквивалент в рельсах.

Ответ 1

Возможно, ваш пример запутан в своей простоте. Я предполагаю, что ваши объекты довольно сложны и что ваш бенчмаркинг показывает, что их создание необоснованно для каждого запроса.

В режиме производства классы не разгружаются между запросами, но экземпляры этих классов. Поэтому использование класса класса похоже на способ пойти ко мне. Просто используйте его для хранения ваших экземпляров.

class ObjectCache
  @@objects = {:beagle => Beagle.new, :poodle => Poodle.new}

  def lookup key
    @@objects[key.to_sym]
  end
end

Ответ 2

Я бы не стал слишком беспокоиться о загрузке и отбрасывании объектов, если вы не можете найти тест, который доказывает, что это проблема. Каждый запрос создает необычное количество промежуточных объектов, как само собой разумеющееся, и они обычно создаются и уничтожаются в течение нескольких миллисекунд.

Как правило, лучше сосредоточиться на загрузке только того, что требуется, де-нормализации базы данных, чтобы выталкивать часто используемые данные или методы в удобное место или сохранять результаты сложных вычислений в поле кеша.

Тест сначала, оптимизируйте только при необходимости.

Сохранение экземпляров моделей в кеш-классе может работать, но это только вариант в производственной среде, где классы моделей не перезагружаются с каждым запросом. Он также может вызывать ошибки, вызванные устаревшими данными.

Если у вас есть проблема масштабирования, которая не может быть решена с помощью этих методов, вам может потребоваться расследовать создание постоянного сервера для части вашей функциональности с использованием комбинации Rack и EventMachine. Существует несколько способов построения фонового процесса, который может выполнять сложные вычисления с использованием предварительно загруженного набора данных, но конкретный подход будет зависеть от нескольких факторов, таких как тип данных, с которыми вы работаете, и как часто он будет доступен.

Ответ 3

В процессе производства контроллеры и классы моделей не перезагружаются между запросами, поэтому у вас есть несколько вариантов:

  • задайте объекты как переменные класса в приложении application_controller
  • создавать методы singleton в самих классах модели, которые возвращают значения

Ответ 4

Да, классы также могут быть предотвращены при разгрузке в режиме разработки. Это не только предмет производства. Хотя это происходит по умолчанию в режиме "Производство", где вы должны вручную установить его в режиме разработки.

Ответ 5

Чтобы ваши классы не перезагружались по каждому запросу даже в режиме разработки, вы можете перемещать их куда-либо за пределы путей автозагрузки (если использовать значения по умолчанию вне каталогов приложений и lib). Таким образом, вы можете использовать эти классы объектов между запросами и, следовательно, использовать их для хранения данных, которые одинаковы для каждого запроса.