OK I did not realise that if different threads import a module then it is 
only imported once and the globals are shared between threads.

I have a number of functions in the module and they all use db extensively. 
If I use db=DAL() or db.reconnect() at each request then that is OK for 
local usage of the db within the model. However now I have to pass db as a 
parameter to each function in the module; or turn the module into a class 
and it is very untidy to use self.db everywhere.

Is there any other way to force each thread/request to use their own 
version of a module with their own version of a db connection; but to make 
the db connection available to all functions within the module.


On Tuesday, 11 December 2012 00:24:40 UTC, Massimo Di Pierro wrote:
>
> You should now make web global. Imagine two requests arrive more or less 
> at the time time. Both call connect? Now you have two threads using the 
> same global web object. You are back to the previous problem. This breaks 
> connection pooling, thread safety, etc.
>
> You either call db = DAL() at each request and db is a local variable of 
> the request (which you call web) or you call db once in your model and use 
> db.reconnect() to duplicate the connection in the thread that is using it 
> (experimental).
>
>
> On Monday, 10 December 2012 10:49:40 UTC-6, simon wrote:
>>
>> OK. I think I have done something similar to your suggestion. It seems to 
>> work but not sure about memory leaks. Also I note there is no web2py method 
>> to close a database connection.
>>
>> I want to put all the code interfacing to a 3rd party system in a single 
>> file. In that way if I change to a different 3rd party package I just need 
>> to change the one file.
>>
>> MODULE:
>>
>> MODEL:
>>     import ocart2
>>     web=ocart2.connect()
>>     rows=web(web.category.category_id>0).select()
>>     log.info((web.tables, rows))
>>
>> MODULE:
>> web=None
>>
>> def connect():
>>     global web
>>     web=DAL(webstring, pool_size=10, migrate=False, migrate_enabled=False)
>>     web.define_table('category',
>>         Field('category_id', 'id', notnull=True, writable=False),
>>         Field('parent_id', 'integer', default=0, notnull=True, 
>> writable=False),
>>         Field('status', 'integer', default=1),
>>         Field('top', 'integer', notnull=True, writable=False))
>>     return web
>>
>>
>>
>>
>>
>> On Monday, 10 December 2012 15:39:34 UTC, Massimo Di Pierro wrote:
>>>
>>> You cannot do this. The connection has to be stablished in the models 
>>> and the tables have to be defined in the models as well.
>>>
>>> The issue is that a db connection only lives within a thread. Since 
>>> web2py is multithreaded at every request you may get a different thread.
>>>
>>>  If is ok to do
>>>
>>> import ocart2
>>> web=ocart2.web()
>>> rows=web(web.category.category_id>0).select()
>>> log.info((web.tables, rows))
>>>
>>> MODULE:
>>> from gluon import *
>>> from config import webstring
>>> def web():
>>>    db = DAL(webstring, pool_size=10, migrate=False, 
>>> migrate_enabled=False)
>>>    db.define_table('category',
>>>      Field('category_id', 'id', notnull=True, writable=False),
>>>      Field('parent_id', 'integer', default=0, notnull=True, 
>>> writable=False),
>>>      Field('status', 'integer', default=1),
>>>      Field('top', 'integer', notnull=True, writable=False))
>>>    return db
>>>
>>> You may also be able to do this:
>>>
>>> MODEL:
>>>
>>> import ocart2
>>> web=ocart2.web
>>> web.reconnect() # <<<
>>> rows=web(web.category.category_id>0).select()
>>> log.info((web.tables, rows))
>>>
>>> MODULE:
>>> from gluon import *
>>> from config import webstring
>>> web=DAL(webstring, pool_size=10, migrate=False, migrate_enabled=False)
>>> web.define_table('category',
>>>     Field('category_id', 'id', notnull=True, writable=False),
>>>     Field('parent_id', 'integer', default=0, notnull=True, 
>>> writable=False),
>>>     Field('status', 'integer', default=1),
>>>     Field('top', 'integer', notnull=True, writable=False))
>>>
>>> Yet the reconnect() method is experimental and I am not sure it does not 
>>> cause a memory leak. Yet you can help me test it.
>>>
>>> On Monday, 10 December 2012 04:13:43 UTC-6, simon wrote:
>>>>
>>>> In my model file I am importing a database definition from a module 
>>>> file.
>>>> This works correctly the first time after the server is started showing 
>>>> the tablename and 11 rows in the table.
>>>> However for the second and subsequent requests it shows a rows object 
>>>> but 0 rows in the table.
>>>> It works fine if I put the model definition code inline rather than 
>>>> importing.
>>>>
>>>> [EDIT: I am fairly sure this used to work. Has something changed? Is 
>>>> there a way to get this to work?]
>>>>
>>>> MODEL:
>>>>
>>>> import ocart2
>>>> web=ocart2.web
>>>> rows=web(web.category.category_id>0).select()
>>>> log.info((web.tables, rows))
>>>>
>>>> MODULE:
>>>> from gluon import *
>>>> from config import webstring
>>>> web=DAL(webstring, pool_size=10, migrate=False, migrate_enabled=False)
>>>> web.define_table('category',
>>>>     Field('category_id', 'id', notnull=True, writable=False),
>>>>     Field('parent_id', 'integer', default=0, notnull=True, 
>>>> writable=False),
>>>>     Field('status', 'integer', default=1),
>>>>     Field('top', 'integer', notnull=True, writable=False))
>>>>
>>>>

-- 



Reply via email to