Deleting singleton object and reconstructing in ruby - ruby-on-rails

I've this situation wherein a singleton class creates object of a model and is used further in my code.
Now, the problem is that occasionally the connection between application and database is broken and all subsequent calls to the singleton fail. While I'm working on fixing the issue, a workaround is required immediately. I believe the solution I'm thinking of, would work but not sure if it will leak memory, cause deadlocks etc.
Here's the original (partial) code:
1 file_path = File.expand_path(File.dirname(__FILE__))
2 require file_path + '/action_factory'
3 require 'erb'
4
5 class Manager
6
7 def initialize(logger)
8 #logger = logger
9 end
10
11 def log_exception(e,method_name)
12 #logger.log :ERROR,"Manager",method_name,'',$$,'',e.backtrace[0] + ": Uncaught Exception " + e.message,DateTime.now,'system',''
13 e.backtrace.shift
14 #logger.log :ERROR,"Manager",method_name,'',$$,''," from " + e.backtrace.join("\n from ") + "(" + e.class.to_s + ")",DateTime.now,'system',''
15 end
16 def execute_action
17 return false if addresses.collect{|a| a if !a.to_s.empty?}.compact.empty?
18 begin
19 action = ActionFactory.instance().get_action(type)
20 return true
21 rescue Exception => e
22 action = nil ####### I'm planning to add this line ####
23 log_exception(e,this_method_name)
24 return false
25 end
26 end
27 end
28 require 'singleton'
29 $file_path=File.expand_path(File.dirname(__FILE__))
30 Dir[$file_path + '/actions/*_action.rb'].each { |filename| require filename }
31
32 class ActionFactory
33 include Singleton
34
35 def get_action(type)
36 action_type_obj = ActionType.find(:first, :select => "action_name", :conditions => ["id=?",type])
37 if(action_type_obj.nil? or action_type_obj.action_name.nil?)
38 raise "Undefined Action Type"
39 else
40 return eval("Actions::#{action_type_obj.action_name}").instance
41 end
42 end
43 end
The problem is that oracle connection is disconnected sometimes and the statement #36 fails returning InvalidStatement exception. All subsequent calls of the statement 19 fail.
I'm planning to add a statement : action = nil in the exception block in line 22. Will that suffice as a workaround or would it bring more issues like memory leakages, deadlocks etc?
If there is a better solution, I'll be glad to hear.
Thanks

Related

Ruby debugger: weird sort of caching

I'm using Ruby debugger gem in my RoR project. Ruby 1.9.3 and Rails 3.2
Debugger works fine by a sort of weird file caching occurs.
I mean:
First example
[4, 13] in /.../app/controllers/fork_controller.rb
4 def index
5
6 debugger
7 a = "hello"
8
=> 9 puts "#{a}"
10
11 end
12
13 def requesting
(rdb:4) eval a
"hello"
(rdb:4) continue
Then I change var "a" to "hello2"
def index
debugger
a = "hello2"
puts "#{a}"
end
this is the result:
[4, 13] in /.../app/controllers/fork_controller.rb
4 def index
5
6 debugger
7 a = "hello"
8
=> 9 puts "#{a}"
10
11 end
12
13 def requesting
(rdb:4) eval a
"hello2"
(rdb:4) continue
So ... the variable evaluation is correct "hello2" instead of "hello" but ... the "breakpoint view" show the first variable content "hello".
What is wrong?
Thanks in advance.

iOS how to understand symbolicated errors

I'm using swift to code. I have symbolicated errors but I still can't understand exactly what the error means. I can see these informations
The class name
The function name
Does it contain any other information like
Line number
Type of error (like array out of index..)
or more?
objc_retain # 0xa
-[PFDecoder decodeDictionary:] # 0x3d, PFDecoder.m : 86
-[PFDecoder decodeObject:] # 0x13, PFDecoder.m : 112
#ERROR!
#ERROR!
#ERROR!
_TFV4Cozy11CozyConfigs14checkAnalyticsfMS0_FT_T_ # 0xa2
_TFC4Cozy11AppDelegate11applicationfS0_FTCSo13UIApplication29didFinishLaunchingWithOptionsGSqGVSs10DictionaryCSo8NSObjectPSs9AnyObject____Sb # 0x18a
_TToFC4Cozy11AppDelegate11applicationfS0_FTCSo13UIApplication29didFinishLaunchingWithOptionsGSqGVSs10DictionaryCSo8NSObjectPSs9AnyObject____Sb # 0x10a
-[NSObject(TLDelegateSW) tlsw_application:didFinishLaunchingWithOptions:] # 0x45
-[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] # 0x117
-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] # 0x933
-[UIApplication _runWithMainScene:transitionContext:completion:] # 0x557
__84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke # 0x23
-[UIApplication workspaceDidEndTransaction:] # 0x81
__31-[FBSSerialQueue performAsync:]_block_invoke # 0xb
__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ # 0xb
__CFRunLoopDoBlocks # 0xd7
__CFRunLoopRun # 0x2f5
CFRunLoopRunSpecific # 0x1db
CFRunLoopRunInMode # 0x69
-[UIApplication _run] # 0x22d
UIApplicationMain # 0x59f
main # 0x86
start # 0x1
This is another crash log which is shorter.(maybe it'll be easier to explain)
_TFFV4Cozy10CardLoader10initializeFMS0_FT4viewGSqCSo6UIView_14tutorialActiveSb_T_U0_FTGSQPSs9AnyObject__GSQCSo7NSError__T_ # 0x2720
_TFFV4Cozy10CardLoader10initializeFMS0_FT4viewGSqCSo6UIView_14tutorialActiveSb_T_U0_FTGSQPSs9AnyObject__GSQCSo7NSError__T_ # 0xe44
__72-[BFTask(Private) continueWithMainThreadResultBlock:executeIfCancelled:]_block_invoke # 0x50, BFTask+Private.m : 52
__41-[BFTask continueWithExecutor:withBlock:]_block_invoke_2 # 0x8, BFTask.m : 287
# 0x13a8
# 0x1368
# 0x597c
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ # 0x8
__CFRunLoopRun # 0x5d0
CFRunLoopRunSpecific # 0x188
# 0xb5a0
UIApplicationMain # 0x5cc
main # 0x70
# 0x2a04
The first one seems like it crashes in the checkAnalytics method of your CozyConfigs class

Elixir/Erlang: Fast lookup with static table

In my application I need to convert integer to some term; for example:
1 → :red
2 → :green
3 → :blue
The table is static, it is known during compilation time and its indices range from <1, n>. There is around 60 of them.
In which way should the table be represented, so the lookup is the fastest? Dict, HashDict, tuple (with kernel.elem()), ets, function with pattern matching...?
As Julius Beckmann suggested in this case functions with pattern matching should be sufficient as they are according to my measurements over 5 times faster than accessing a map.
Below you can find an implementation of what you are looking for (benchmark code included at the bottom):
defmodule TermLookUpByInteger do
#term_by_integer %{
1 => :aa, 11 => :ba, 21 => :ca, 31 => :da, 41 => :ea, 51 => :fa, 61 => :ga,
2 => :ab, 12 => :bb, 22 => :cb, 32 => :db, 42 => :eb, 52 => :fb, 62 => :gb,
3 => :ac, 13 => :bc, 23 => :cc, 33 => :dc, 43 => :ec, 53 => :fc, 63 => :gc,
4 => :ad, 14 => :bd, 24 => :cd, 34 => :dd, 44 => :ed, 54 => :fd, 64 => :gd,
5 => :ae, 15 => :be, 25 => :ce, 35 => :de, 45 => :ee, 55 => :fe, 65 => :ge,
6 => :af, 16 => :bf, 26 => :cf, 36 => :df, 46 => :ef, 56 => :ff, 66 => :gf,
7 => :ag, 17 => :bg, 27 => :cg, 37 => :dg, 47 => :eg, 57 => :fg, 67 => :gg,
8 => :ah, 18 => :bh, 28 => :ch, 38 => :dh, 48 => :eh, 58 => :fh, 68 => :gh,
9 => :ai, 19 => :bi, 29 => :ci, 39 => :di, 49 => :ei, 59 => :fi, 69 => :gi,
0 => :aj, 10 => :bj, 20 => :cj, 30 => :dj, 40 => :ej, 50 => :fj, 60 => :gj,
}
#doc """
iex> TermLookUpByInteger.lookup_pmf(2)
:ab
"""
def lookup_pmf(int), do: do_lookup(int)
for {int, term} <- #term_by_integer do
defp do_lookup(unquote(int)), do: unquote(term)
end
#doc """
iex> TermLookUpByInteger.lookup_m(3)
:ac
"""
def lookup_m(int), do: #term_by_integer[int]
end
# Benchmark:
n = 1_000_000
range = 1..(n)
measure = fn fun -> :timer.tc(fn -> for _ <- range, do: fun.() end) end
{time_pmf, _result} = measure.(fn -> TermLookUpByInteger.lookup_pmf(:random.uniform(60)) end)
{time_m, _result} = measure.(fn -> TermLookUpByInteger.lookup_m(:random.uniform(60)) end)
IO.puts " Sample size: #{n}"
IO.puts "Pattern matching functions lookup: #{time_pmf/1000} ms"
IO.puts " Map lookup: #{time_m/1000} ms"
IO.puts " Absolute Difference: #{(time_pmf-time_m)/1000} ms"
IO.puts " Relative Difference: #{round((time_pmf-time_m)/time_m*100)}%"
IO.puts " Faster: x #{Float.round(time_m/time_pmf, 2)} times"
Results:
Sample size: 1000000
Pattern matching functions lookup: 447.6 ms
Map lookup: 2423.517 ms
Absolute Difference: -1975.917 ms
Relative Difference: -82%
Faster: x 5.41 times
I hope that will be useful.
If the map is completely static and will not change, you can use generated pattern matching. This will be the fastest way to integrate that lookup in your application.
Some example code, reading these mappings from a external file: https://github.com/h4cc/slugger/blob/master/lib/slugger.ex#L69-72
Instead of using a external file, your source map data can be held in a #attribute.
Even if new mappings will be needed on runtime, these could be handled with a catchall-pattern match doing a lookup in a HashDict.
If you rely on fast access from many processes, then mochiglobal may be the answer. It's tricky constant pool, which keeps keys and values as functions in module. Every time you put/2 something, module is recompiled (it's slow but doesn't matter in your case). With this approach value is not copied into process heap as it is function call. Here is better explanation.

Add seconds (in fixnum format) to a datetime, Rails

I need to pass a variable to my view with Time.now + #seconds in time format (i.e. 12pm + 3600 seconds = 1:00pm, which goes to the view).
Time.now + #seconds #seconds is a fixnum
doesn't work because "Time can't be coerced into Fixnum". How then can I generate this simple result?
Don't barbeque me if this is wrong now but back when I was doing Rails you would just say Time.now + #seconds.seconds . Also #seconds.seconds.from_now
Today I learned that (1.second + DateTime.now) != (DateTime.now + 1.second)
to answer your question try using Time.now + #seconds.seconds or Time.now + #seconds.to_i.seconds
Another example
DateTime.current + 20.seconds
=> Mon, 11 Jan 2021 18:06:04 +0000

"no block given" errors with cache_money

i've inherited a site that in production is generating dozens of "no block given" exceptions every 5 minutes.
the top of the stack trace is:
vendor/gems/nkallen-cache-money-0.2.5/lib/cash/accessor.rb:42:in `add'
vendor/gems/nkallen-cache-money-0.2.5/lib/cash/accessor.rb:33:in `get'
vendor/gems/nkallen-cache-money-0.2.5/lib/cash/accessor.rb:22:in `call'
vendor/gems/nkallen-cache-money-0.2.5/lib/cash/accessor.rb:22:in `fetch'
vendor/gems/nkallen-cache-money-0.2.5/lib/cash/accessor.rb:31:in `get'
so it appears that the problem is in the cache money plugin.
has anyone experienced something similar?
i've cut and pasted the relevant code below -- anyone more familiar with blocks able to discern any obvious problems?
11 def fetch(keys, options = {}, &block)
12 case keys
13 when Array
14 keys = keys.collect { |key| cache_key(key) }
15 hits = repository.get_multi(keys)
16 if (missed_keys = keys - hits.keys).any?
17 missed_values = block.call(missed_keys)
18 hits.merge!(missed_keys.zip(Array(missed_values)).to_hash)
19 end
20 hits
21 else
22 repository.get(cache_key(keys), options[:raw]) || (block ? block.call : nil)
23 end
24 end
25
26 def get(keys, options = {}, &block)
27 case keys
28 when Array
29 fetch(keys, options, &block)
30 else
31 fetch(keys, options) do
32 if block_given?
33 add(keys, result = yield(keys), options)
34 result
35 end
36 end
37 end
38 end
39
40 def add(key, value, options = {})
41 if repository.add(cache_key(key), value, options[:ttl] || 0, options[:raw]) == "NOT_STORED\r\n"
42 yield
43 end
44 end
line 33 is calling add, but not passing a block, though one is expected on line 42 and there's no block_given? check like there is in the get method. There doesn't really seem to be an appropriate block to pass in this case, as the block passed to get is already yielded to in the add call on line 33, so passing it again separately to add is probably not correct.
Changing line 42 to yield if block_given? should fix your error in this case and shouldn't cause problems elsewhere.
It's also worth noting that line 42 is only called if something was not stored, so you may want to look into why that's happening.

Resources