On Tuesday, April 24, 2012 12:58:41 PM UTC-7, Rodrigo Rosenfeld Rosas wrote:
>
>  This shouldn't be "really hard":
>
>   conn = DB.synchronize{|c| c}
>  
>
>
> Humm, this is what I was looking for. I didn't realize how to get the 
> connection from the pool without releasing it at the end of the block. I 
> thought that synchronized would release the connection, but if it doesn't, 
> this is great!
>

It's important to understand what that piece of code does.  It allows you 
to get a reference to the connection, while still returning the connection 
to the pool.  Operating on that connection is completely unsafe in threaded 
code, as the connection might already be used by another thread.  In 
single-threaded code, it should be safe. 
Sorry this is where I got confused. Could you please give me a concrete 
example?

>  
> Thread 1: get connection from pool, issue BEGIN query, return connection 
> to pool
>  
> The way to do that is checking out a connection at the start of the 
> transaction block, and checking in the connection at the end of the 
> transaction block.  You cannot just checkout a connection to issue the 
> BEGIN and then check the connection back in, as the connection code 
> theoretically be used by other threads that should not be operating inside 
> the transaction.
>
> This is what I find weird. In what situation Thread 1 would return the 
> connection to the pool before finishing the transaction logic? That doesn't 
> make any sense to me in real application scenarios.
>

 With Sequel's block based transaction approach, it wouldn't.  However, if 
you don't use a block based approach, you have two possibilities:

1) Return the connection to the pool before you are finished using it.
2) Leak the connection instead of returning it to the pool.


>  Also when the before(:each) is called, Sequel.transaction wouldn't know 
>> what is the current depth level.
>>  
>
> Calling the internal transaction methods lets Sequel keep track of the 
> depth.
>  
>
> You mean DB.send(:_transaction), right?
>

Well, not that method specifically (since it uses a block-based approach), 
but the other internal send methods that I used in my earlier example.
 

>   
>
>  So, as you can see, I'm totally lost on how to approach that.
>>
>> If I was going to run my specs concurrently, I'd make sure that a 
>> different connection would be used for each "describe" block and I wouldn't 
>> run multiple examples of the same outer-most block concurrently.
>>  
>
> My approach is incompatible with concurrent specs.  You really do need to 
> implement around(:all) for that.
>  
>
> Yeah, I'll try to worry about that when I need to. Another approach would 
> be use multiple processes and different databases to run the specs in 
> parallel but still using a single thread per process so I could work around 
> this.
>   
>

That's one option. I have thought of a way to get the transaction code I 
gave above to work in the multithreaded case, but you have to hack the 
connection pool.  Using the default threaded connection pool:

  conn = DB.pool.acquire(Thread.current)
  DB.send(:add_transaction, conn, {})
  DB.send(:begin_transaction, conn, {})
  DB.transaction(:savepoint=>true){}
  DB.send(:begin_transaction, conn, :savepoint=>true)
  DB.send(:rollback_transaction, conn, :savepoint=>true)
  DB.send(:remove_transaction, conn, false)
  DB.send(:begin_transaction, conn, :savepoint=>true)
  DB.send(:begin_transaction, conn, :savepoint=>true)
  DB.transaction(:savepoint=>true, :rollback=>:always){}
  DB.send(:rollback_transaction, conn, :savepoint=>true)
  DB.send(:remove_transaction, conn, false)
  DB.send(:rollback_transaction, conn, :savepoint=>true)
  DB.send(:remove_transaction, conn, false)
  DB.send(:rollback_transaction, conn, {})
  DB.send(:remove_transaction, conn, false)
  DB.pool.send(:sync){DB.pool.send(:release, Thread.current)}

Jeremy

>

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sequel-talk/-/a2M9I3UEg0wJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sequel-talk?hl=en.

Reply via email to