PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Saturday, November 12, 2022

[FIXED] when sharing data via memcached between Rails and Sinatra, how fix Sinatra not handling ActiveSupport

 November 12, 2022     memcached, ruby-on-rails, sinatra     No comments   

Issue

Is there any way to cause Sinatra to transparently handle cached data correctly that was written by Rails, eg, to implicitly handle the ActiveSupport class that Rails uses when it stores data?

A Heroku-hosted Rails 4 app and a Sinatra app used a shared Memcachier store to share certain ephemeral data.

If a key/value is created on Sinatra, everything works normally:

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

will set a key that either the Sinatra app or the Rails app can read, and either app will automatically read nil once it expires in 100 seconds. And both Rails and Sinatra report the class of the data value to be String.

However, if the data is set by the Rails app:

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

the Rails app read returns a String (as expected), but Sinatra app get returns class 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>

and if the Sinatra app fetches the same key after the expiry, the same data is returned (not nil).

It is certainly possible on the Sinatra app to brute-force it with a new method that get's the data, and manually handles expiration and data issues using ActiveSupport::Cache::Entry methods, as outlined below.

But it seems like there ought to be some way to have the ActiveSupport::Cache::Entry code handle those details automatically by telling Sinatra to use ActiveSupport::Cache for both setting and getting data?

# 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

Currently the memcache store is configured as per Heroku online documentation:

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
 })

EDIT - SOLVED Per accepted answer the key to Sinatra/Rails data interoperability was to explicitly configure the cache store to use ActiveSupport, which still automagically uses the Dalli gem to manage the connection to the memcachier service.

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

which also means using the settings.cache.read/write methods (vs the settings.cache.get/set methods used when you configure using Dalli::Client.new).

ADDITIONAL EDIT:

When using the cache inside a model, you cannot access settings.cache directly, need to use Sinatra::Application.settings.cache.read()


Solution

I am not a Sinatra user, Used something like the below in 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")

EDIT

It seems you are using gem dalli, You can also use the DalliStore instead of MemCacheStore like the below:

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")



Answered By - user11350468
Answer Checked By - Katrina (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

1,216,061

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © 2025 PHPFixing