Comments (2)
Yeah this just hit me with postgres too.
This email explains what it means: http://www.postgresql.org/message-id/[email protected]
a lock on a select result means that
you've guaranteed that no one else can change the rows you selected.
In an outer join it's impossible to guarantee that --- someone could
insert a B row that matches a formerly unmatched A row. If you now
re-did the SELECT you would get a different result, ie, your
null-extended A row would be replaced by a normal row, even though you
had lock on that A row. (This does not speak to the question of new
rows showing up in the second SELECT --- that's always possible. The
point is that a row you got the first time is now different despite
being "locked".)
from django-bitcoin.
The issue is that wallet__isnull=True
is attempting to lock the null wallet
rows and the other statements are trying to lock the addresses
table, the thing is postgres can't guarantee that for the transaction the wallet result will stay constant, as far as postgres knows some other transaction could run in parallel and change an entry in the wallet
table making it's old statement invalid
It's not a perfect solution but if you need a workaround for now you can add a distributed lock on the new_bitcoin_address
to ensure that the function doesn't run in parallel any two times in the system:
@distributedlock('get_new_address') def new_bitcoin_address():
Update this line in the 'new_bitcoin_address' function:
updated = BitcoinAddress.objects.select_for_update().filter(id=bp.id, active=False, least_received__lte=0, wallet__isnull=True).update(active=True)
with
updated = BitcoinAddress.objects.select_for_update().filter(id=bp.id).update(active=True)
The criteria are already set by bp.id, so long as nothing has utilized that address within the same timeframe of this occurrence of the function there will be no issues with duplicity in the database. That is the reason for the distributed lock, ensuring that the function cannot run in parallel within your app.
For the same reason you also have to modify the call in the Wallet.receiving_address method.
This
updated = BitcoinAddress.objects.select_for_update().filter(id=addr.id, active=True, least_received__lte=0, wallet__isnull=True).update(active=True, wallet=self)
becomes
updated = BitcoinAddress.objects.select_for_update().filter(id=addr.id, active=True).update(wallet=self)
The addr
variable at this point should direct towards an address id, there is no reason to run the rest of the criteria since it's been executed already, arguably active=True
isn't necessary at this point, as it should have been set in the new_bitcoin_address
call. There is also no reason for the active=True
portion in the update()
call at the end of the function since it was already set in the new_bitcoin_address
I hope that helps, there has to be a better way but unfortunately with the way it is built right now it'll take some design overhauls or a manual select statement that doesn't use an outer join, unfortunately I am not an SQL genius :(.
from django-bitcoin.
Related Issues (18)
- Security issue on running installations (fixed 2012-09-09)
- TypeError: string indices must be integers on running 'CheckTransactions' HOT 1
- Bitcoincharts API error HOT 2
- receiving_address() raises TransactionManagementError HOT 2
- receiving_address() is generating more that one address
- get_or_create() do not save the bitcoinaddress into the database
- Deprecated API bitcoincharts.com
- TransactionManagementError when trying Wallet.send_to_address
- WalletTransaction doen't map with DepositTransaction
- transaction with no fee raises "Updated amount not matchinf transaction amount!"
- Django-bitcoin ignores "generate" transations
- Convert to work with Python 3 HOT 2
- raise exception
- Amount is reduced after a failed transaction HOT 1
- Looking for forks HOT 1
- Application using django-bitcoin is unaware of transaction fees HOT 1
- Better QR code generation HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-bitcoin.