ruby-on-rails - 当 Rails 和 Sinatra 之间通过 memcached 共享数据时,如何修复 Sinatra 不处理 ActiveSupport

标签 ruby-on-rails sinatra memcached

是否有任何方法可以使 Sinatra 透明地正确处理由 Rails 编写的缓存数据,例如,隐式处理 Rails 在存储数据时使用的 ActiveSupport 类?

Heroku 托管的 Rails 4 应用程序和 Sinatra 应用程序使用共享的 Memcachier 存储来共享某些临时数据。

如果在 Sinatra 上创建了键/值,则一切正常:

# on Sinatra:
session.cache.set("foo", "from sinatra", 100)

将设置一个Sinatra应用程序或Rails应用程序可以读取的 key ,并且一旦它在100秒内过期,任何一个应用程序都会自动读取nilRails 和 Sinatra 都将数据值的类报告为 String。

但是,如果数据是由 Rails 应用程序设置的:

# on Rails:
Rails.cache.write("foo", "from rails", expires_in: 100)

Rails 应用程序 read 返回一个字符串(如预期),但 Sinatra 应用程序 get 返回类 ActiveSupport::Cache::Entry

# on Sinatra
d = settings.cache.get("foo")
=> #<ActiveSupport::Cache::Entry:0x7f7ea70 @value="from rails", @created_at=1598330468.8312092, @expires_in=100.0>

如果 Sinatra 应用在过期后获取相同的 key ,则返回相同数据(不是零)。

在 Sinatra 应用程序上当然可以使用一种新方法来暴力破解它,获取数据,并使用 ActiveSupport 手动处理过期和数据问题::Cache::Entry 方法,如下所述。

但似乎应该有某种方法让 ActiveSupport::Cache::Entry 代码自动处理这些细节,告诉 Sinatra 使用 ActiveSupport::Cache 进行设置和获取数据。 ?

# pseudo code for Sinatra app
 def new_get(key)
   x = settings.cache.get(key)
   if x.class == ActiveSupport::Cache::Entry
      if x.expired?
         x.delete
         return nil 
      else return x.value
   else return x
 end

目前,memcache 存储是根据 Heroku 在线文档配置的:

require 'dalli'
set :cache, Dalli::Client.new(
 (ENV["MEMCACHIER_SERVERS"] || "").split(","),
 {:username => ENV["MEMCACHIER_USERNAME"],
  :password => ENV["MEMCACHIER_PASSWORD"],
  :failover => true, # default is true
  :socket_timeout => 1.5, # default is 0.5
  :socket_failure_delay => 0.2, # default is 0.01
  :down_retry_delay => 60 # default is 60
 })

编辑 - 已解决 根据接受的答案,Sinatra/Rails 数据互操作性的关键是显式配置缓存存储以使用 ActiveSupport,它仍然自动使用 Dalli gem 来管理与 memcachier 服务的连接.

set :cache, ActiveSupport::Cache::MemCacheStore.new(
... # init parameters
)}

这也意味着使用 settings.cache.read/write 方法(与使用 Dalli::Client 配置时使用的 settings.cache.get/set 方法相比) .新)。

额外编辑:

在模型内部使用缓存时,无法直接访问settings.cache,需要使用Sinatra::Application.settings.cache.read()

最佳答案

我不是 Sinatra 用户,在 Rails 中使用过类似下面的内容。

cache_store = ActiveSupport::Cache::MemCacheStore.new('localhost')

# For writing the keys:
cache_store.write("foo", "from rails", expires_in: 100)

# For reading the keys
cache_store.read("foo")

编辑

看来您正在使用 gem dalli ,您还可以使用 DalliStore 代替 MemCacheStore,如下所示:

cache_store = ActiveSupport::Cache::DalliStore.new('localhost')
# For writing the keys:
cache_store.write("foo", "from rails", expires_in: 100)
    
# For reading the keys
cache_store.read("foo")

关于ruby-on-rails - 当 Rails 和 Sinatra 之间通过 memcached 共享数据时,如何修复 Sinatra 不处理 ActiveSupport,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63572308/

相关文章:

javascript - 尊重从 HTML 显示中的 API 响应返回的 "\n"换行符(和特殊字符)

ruby-on-rails - 一个 Controller 的 Rails 多个 namespace

ruby-on-rails - Ruby 中 StringIO 的未定义方法 'path'

ruby-on-rails - 使用 Rails 将外部 JSON 保存到数据库

mysql - 从数据库创建新闻源作为源

ruby - Sinatra 子目录 View

ruby - 如何创建和测试特定于环境的代码?

json - 将 JSON 解码为 Go 接口(interface){}

REST API 缓存,我应该使用反向代理还是 memcache(d)?

java - 无法使用 Java 或 Rest api 从 memcached 存储桶获取从 .NET 序列化的值