111 lines
4.3 KiB
Ruby
111 lines
4.3 KiB
Ruby
module Canvas
|
|
# defines the behavior when a protected attribute is assigned to in mass
|
|
# assignment. The default, and Rails' normal behavior, is to just :log. Set
|
|
# this to :raise to raise an exception.
|
|
mattr_accessor :protected_attribute_error
|
|
|
|
# defines the behavior around casting arguments passed into dynamic finders.
|
|
# Arguments are coerced to the appropriate type (if the column exists), so
|
|
# things like find_by_id('123') become find_by_id(123). The default (:log)
|
|
# logs a warning if the cast isn't clean (e.g. '123a' -> 123 or '' -> 0).
|
|
# Set this to :raise to raise an error on unclean casts.
|
|
mattr_accessor :dynamic_finder_type_cast_error
|
|
|
|
# defines the behavior when nil or empty array arguments passed into dynamic
|
|
# finders. The default (:log) logs a warning if the finder is not scoped and
|
|
# if *all* arguments are nil/[], e.g.
|
|
# Thing.find_by_foo_and_bar(nil, nil) # warning
|
|
# Other.find_by_baz([]) # warning
|
|
# Another.find_all_by_a_and_b(123, nil) # ok
|
|
# ThisThing.some_scope.find_by_whatsit(nil) # ok
|
|
# Set this to :raise to raise an exception.
|
|
mattr_accessor :dynamic_finder_nil_arguments_error
|
|
|
|
def self.active_record_foreign_key_check(name, type, options)
|
|
if name.to_s =~ /_id\z/ && type.to_s == 'integer' && options[:limit].to_i < 8
|
|
raise ArgumentError, "All foreign keys need to be 8-byte integers. #{name} looks like a foreign key to me, please add this option: `:limit => 8`"
|
|
end
|
|
end
|
|
|
|
def self.redis
|
|
return @redis if @redis
|
|
# create the redis cluster connection using config/redis.yml
|
|
redis_settings = Setting.from_config('redis')
|
|
raise("Redis is not enabled for this install") if redis_settings.blank?
|
|
Bundler.require 'redis'
|
|
if redis_settings.is_a?(Array)
|
|
redis_settings = { :servers => redis_settings }
|
|
end
|
|
# convert string addresses to options hash, and disable redis-cache's built-in marshalling code
|
|
redis_settings[:servers].map! { |s|
|
|
::Redis::Factory.convert_to_redis_client_options(s).merge(:marshalling => false)
|
|
}
|
|
@redis = ::Redis::Factory.create(redis_settings[:servers])
|
|
if redis_settings[:database].present?
|
|
@redis.select(redis_settings[:database])
|
|
end
|
|
@redis
|
|
end
|
|
|
|
def self.redis_enabled?
|
|
@redis_enabled ||= Setting.from_config('redis').present?
|
|
end
|
|
|
|
def self.cache_store_config
|
|
cache_store_config = {
|
|
'cache_store' => 'mem_cache_store',
|
|
}.merge(Setting.from_config('cache_store') || {})
|
|
config = nil
|
|
case cache_store_config.delete('cache_store')
|
|
when 'mem_cache_store'
|
|
cache_store_config['namespace'] ||= cache_store_config['key']
|
|
servers = cache_store_config['servers'] || (Setting.from_config('memcache'))
|
|
if servers
|
|
config = :mem_cache_store, servers, cache_store_config
|
|
end
|
|
when 'redis_store'
|
|
Bundler.require 'redis'
|
|
Canvas::Redis.patch
|
|
# merge in redis.yml, but give precedence to cache_store.yml
|
|
#
|
|
# the only options currently supported in redis-cache are the list of
|
|
# servers, not key prefix or database names.
|
|
cache_store_config = (Setting.from_config('redis') || {}).merge(cache_store_config)
|
|
cache_store_config['key_prefix'] ||= cache_store_config['key']
|
|
servers = cache_store_config['servers']
|
|
config = :redis_store, servers
|
|
end
|
|
unless config
|
|
config = :nil_store
|
|
end
|
|
config
|
|
end
|
|
|
|
# `sample` reports KB, not B
|
|
if File.directory?("/proc")
|
|
# linux w/ proc fs
|
|
LINUX_PAGE_SIZE = (size = `getconf PAGESIZE`.to_i; size > 0 ? size : 4096)
|
|
LINUX_HZ = 100.0 # this isn't always true, but it usually is
|
|
def self.sample_memory
|
|
s = File.read("/proc/#{Process.pid}/statm").to_i rescue 0
|
|
s * LINUX_PAGE_SIZE / 1024
|
|
end
|
|
# returns [ utime, stime ], both in seconds
|
|
def self.sample_cpu_time
|
|
a = File.read("/proc/#{Process.pid}/stat").split(" ") rescue nil
|
|
[ a[13].to_f / LINUX_HZ, a[14].to_f / LINUX_HZ] if a && a.length >= 15
|
|
end
|
|
else
|
|
# generic unix solution
|
|
def self.sample_memory
|
|
# hmm this is actually resident set size, doesn't include swapped-to-disk
|
|
# memory.
|
|
`ps -o rss= -p #{Process.pid}`.to_i
|
|
end
|
|
def self.sample_cpu_time
|
|
# TODO: use ps to grab this
|
|
[ 0, 0 ]
|
|
end
|
|
end
|
|
end
|