Skip to content

Commit

Permalink
REFACTOR: distributed_cache is moved to the message_bus gem
Browse files Browse the repository at this point in the history
  • Loading branch information
nlalonde committed Oct 15, 2018
1 parent 99d1ded commit d166c38
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 281 deletions.
155 changes: 8 additions & 147 deletions lib/distributed_cache.rb
Original file line number Diff line number Diff line change
@@ -1,153 +1,14 @@
# frozen_string_literal: true

# Like a hash, just does its best to stay in sync across the farm
# On boot all instances are blank, but they populate as various processes
# fill it up

require 'weakref'
require 'base64'

class DistributedCache

class Manager
CHANNEL_NAME ||= '/distributed_hash'.freeze

def initialize(message_bus = nil)
@subscribers = []
@subscribed = false
@lock = Mutex.new
@message_bus = message_bus || MessageBus
end

def subscribers
@subscribers
end

def process_message(message)
i = @subscribers.length - 1

payload = message.data

while i >= 0
begin
current = @subscribers[i]

next if payload["origin"] == current.identity && !Rails.env.test?
next if current.key != payload["hash_key"]
next if payload["discourse_version"] != Discourse.git_version

hash = current.hash(message.site_id)

case payload["op"]
when "set" then hash[payload["key"]] = payload["marshalled"] ? Marshal.load(Base64.decode64(payload["value"])) : payload["value"]
when "delete" then hash.delete(payload["key"])
when "clear" then hash.clear
end

rescue WeakRef::RefError
@subscribers.delete_at(i)
ensure
i -= 1
end
end
end

def ensure_subscribe!
return if @subscribed
@lock.synchronize do
return if @subscribed
@message_bus.subscribe(CHANNEL_NAME) do |message|
@lock.synchronize do
process_message(message)
end
end
@subscribed = true
end
end

def publish(hash, message)
message[:origin] = hash.identity
message[:hash_key] = hash.key
message[:discourse_version] = Discourse.git_version
@message_bus.publish(CHANNEL_NAME, message, user_ids: [-1])
end

def set(hash, key, value)
# special support for set
marshal = (Set === value || Hash === value || Array === value)
value = Base64.encode64(Marshal.dump(value)) if marshal
publish(hash, op: :set, key: key, value: value, marshalled: marshal)
end

def delete(hash, key)
publish(hash, op: :delete, key: key)
end

def clear(hash)
publish(hash, op: :clear)
end

def register(hash)
@lock.synchronize do
@subscribers << WeakRef.new(hash)
end
end
end

@default_manager = Manager.new

def self.default_manager
@default_manager
end

attr_reader :key
require 'message_bus/distributed_cache'

class DistributedCache < MessageBus::DistributedCache
def initialize(key, manager: nil, namespace: true)
@key = key
@data = {}
@manager = manager || DistributedCache.default_manager
@namespace = namespace

@manager.ensure_subscribe!
@manager.register(self)
super(
key,
manager: manager,
namespace: namespace,
app_version: Discourse.git_version
)
end

def identity
# fork resilient / multi machine identity
(@seed_id ||= SecureRandom.hex) + "#{Process.pid}"
end

def []=(k, v)
k = k.to_s if Symbol === k
@manager.set(self, k, v)
hash[k] = v
end

def [](k)
k = k.to_s if Symbol === k
hash[k]
end

def delete(k, publish: true)
k = k.to_s if Symbol === k
@manager.delete(self, k) if publish
hash.delete(k)
end

def clear
@manager.clear(self)
hash.clear
end

def hash(db = nil)
db =
if @namespace
db || RailsMultisite::ConnectionManagement.current_db
else
RailsMultisite::ConnectionManagement::DEFAULT
end

@data[db] ||= ThreadSafe::Hash.new
end

end
134 changes: 0 additions & 134 deletions spec/components/distributed_cache_spec.rb

This file was deleted.

0 comments on commit d166c38

Please sign in to comment.