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))
>>>>
>>>>
--