Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow persistence plugins to commit as a final step. #568

Merged
merged 5 commits into from
Jan 23, 2019

Conversation

jsolman
Copy link
Contributor

@jsolman jsolman commented Jan 21, 2019

If there are multiple persistence plugins loaded and one of them throws an exception, then none of them should actually commit anything to a persistent store. To facilitate this behavior, I added an OnCommit method to be called after all plugins have had a chance to process results from OnPersist and throw if something was wrong.

A persistence plugin implementing IPersistencePlugin should do any processing needed to stage data to persist in its OnPersist method, and then perform actual persistence in its OnCommit method. In this way database integrity is maximized.

@erikzhang
Copy link
Member

However, if a plugin throws an exception on OnCommit(), the remaining plugins will not be able to execute the OnCommit() method properly.

@shargon
Copy link
Member

shargon commented Jan 22, 2019

Why do you need both cases? maybe we can remove OnPersist?

@erikzhang
Copy link
Member

OnPersist() allows plugins to terminate the persistence process by throwing exceptions. I think that OnCommit() is not necessary.

@jsolman
Copy link
Contributor Author

jsolman commented Jan 22, 2019

OnPersist() allows plugins to terminate the persistence process by throwing exceptions. I think that OnCommit() is not necessary.

There can be multiple persistence plugins. If there are 3 and last one that runs throws, and the other 2 have already persisted, it is a problem. If they do their processing in OnPersist and then do the work to actually write to disk in OnCommit the risk is minimized of getting in an inconsistent state due to some processing problem in OnPersist that could cause a plugin to throw an exception.

I changed the code so that OnCommit for the plugins happens before snapshot.commit is called since you expressed concern about them throwing in OnCommit.

@jsolman jsolman requested a review from shargon January 22, 2019 17:42
@vncoelho
Copy link
Member

I agree with @erikzhang . I think that this OnCommit() is not needed now.

@jsolman, while we have more plugins there are also additional switch cases on the OnPersist functions, thus, in such scenarios, they could communicate in that level as well, right?

@jsolman
Copy link
Contributor Author

jsolman commented Jan 22, 2019

@vncoelho Why do you think it isn't needed right now? Some people have more than one persistence plugin? Why should an exception in processing notifications in the second plugin still allow the first to commit? This is what would happen now without having OnCommit() as a separate step?

@jsolman
Copy link
Contributor Author

jsolman commented Jan 22, 2019

We can wait to merge this, but I'm still not seeing why it isn't helpful.

@vncoelho
Copy link
Member

I think that you can add a switch case in the plugin itself.
Jeff, I do not see why to not parallelize the plugin in its file, if you need to run more than one.

@jsolman
Copy link
Contributor Author

jsolman commented Jan 22, 2019

@jsolman, while we have more plugins there are also additional switch cases on the OnPersist functions, thus, in such scenarios, they could communicate in that level as well, right?

I’m not following you, even if there were a way for plugins to communicate from one OnPersist function to the next; the previous one could have already committed, the next that is going to throw an exception cannot undo it...

@jsolman
Copy link
Contributor Author

jsolman commented Jan 22, 2019

@vncoelho Plugins are meant to be self contained. They should not have to coordinate on state and have some final plugin commit or something like that. That is a suboptimal design.

@erikzhang
Copy link
Member

We can call OnCommit() after snapshot.Commit() and then catch the exceptions thrown by each plugin in OnCommit() so that at least the plugins don't interact with each other.

@jsolman
Copy link
Contributor Author

jsolman commented Jan 23, 2019

@erikzhang Switching back to calling after snapshot.Commit() and catching exceptions seems reasonable to me, but maybe we should delegate whether it should crash the node to the plugin, because if we catch the exceptions the node operator might not realize their plugin is misbehaving occasionally.

Also, some node operators might really want a plugin commit failing to crash the node.

What about having a method in the plugin that gets called with the exception if it occurs during commit:

bool ShouldThrowExceptionFromCommit(Exception ex);

That method could return a value to specify whether or not the exception should be rethrown and crash the node. That way the plugin could choose to log the exception and not crash, or it could choose to have the exception rethrown.

Also it can wait till running all of the plugins OnCommit Methods, before actually rethrowing if one of the plugins chooses to throw and crash.

neo/Ledger/Blockchain.cs Outdated Show resolved Hide resolved
neo/Ledger/Blockchain.cs Outdated Show resolved Hide resolved
@vncoelho
Copy link
Member

@jsolman, looks good now after the snapshot.commit (just now I got that this was your initial intention. When I revised it was aligned with the Persist.)

@shargon shargon merged commit bbbc0cf into master Jan 23, 2019
@shargon shargon deleted the PersistenceOnCommit branch January 23, 2019 22:07
txhsl added a commit to txhsl/neo that referenced this pull request Feb 25, 2019
* Handles escape characters in JSON

*  Pass ApplicationExecution to IPersistencePlugin (neo-project#531)

* Update dependencies: (neo-project#532)

- Akka 1.3.11
- Microsoft.AspNetCore.ResponseCompression 2.2.0
- Microsoft.AspNetCore.Server.Kestrel 2.2.0
- Microsoft.AspNetCore.Server.Kestrel.Https 2.2.0
- Microsoft.AspNetCore.WebSockets 2.2.0
- Microsoft.EntityFrameworkCore.Sqlite 2.2.0
- Microsoft.Extensions.Configuration.Json 2.2.0

* change version to v2.9.4

* Updating Unknown to Policy Fail (neo-project#533)

* Fix a dead lock in `WalletIndexer`

* Downgrade Sqlite to 2.1.4 (neo-project#535)

* RPC call gettransactionheight (neo-project#541)

* getrawtransactionheight

Nowadays two calls are need to get a transaction height, `getrawtransaction` with `verbose` and then use the `blockhash`.
Other option is to use `confirmations`, but it can be misleading.

* Minnor fix

* Shargon's tip

* modified

* Allow to use the wallet inside a RPC plugin (neo-project#536)

* Improve Large MemoryPool Performance - Sort + intelligent TX reverification (neo-project#500)

Improve Large MemoryPool Performance - Sort + intelligent TX reverification (neo-project#500)

* Keep both verified and unverified (previously verified) transactions in sorted trees so ejecting transactions above the pool size is a low latency operation.
* Re-verify unverified transactions when Blockchain actor is idle.
* Don't re-verify transactions needlessly when not at the tip of the chain.
* Support passing a flag to `getrawmempool` to retrieve both verified and unverified TX hashes.
* Support MaxTransactionsPerBlock and MaxFreeTransactionsPerBlock from Policy plugins.
* Rebroadcast re-verified transactions if it has been a while since last broadcast (high priority transactions are rebroadcast more frequently than low priority transactions.

* Policy filter GetRelayResult message (neo-project#543)

* Policy filter GetRelayResult message

* adding fixed numbering for return codes

* Removed enum fixed values

* Add some initial MemoryPool unit tests. Fix bug when Persisting the GenesisBlock (neo-project#549)

* More MemoryPool Unit Tests. Improve Re-broadcast back-off to an increasing linear formula. (neo-project#554)

* Ensuring Object Reference check of SortedSets for speed-up (neo-project#557)

* Minor comments update on Mempool class (neo-project#556)

* Update MemoryPool Unit Test to add random fees to Mock Transactions (neo-project#558)

* Add Unit Test for MemoryPool sort order. Fixed sort order to return descending. (neo-project#559)

* Add unit test to verify memory pool sort order and reverification order. Fixed sort order bug.

* VerifyCanTransactionFitInPool works as intended. Also inadvertantly verified GetLowestFeeTransaction() works.

* Benchmark structure for UInt classes (neo-project#553)

* basic benchmark structure for UInt classes

* commented code2 from lights for now

* updated tests. all seem correct now

* Switch to using a benchmark method taking a method delegate to benchmark.

* Make pass.

* 1 million iterations.

* Switch to ulong for the 4th option, and it is still the same speed.

* fix test data for 50% equal data

* make test pass

* neo.UnitTests/UT_UIntBenchmarks.cs

* neo.UnitTests/UT_UIntBenchmarks.cs

* Base 20 - UInt160 tests

* neo.UnitTests/UT_UIntBenchmarks.cs

* inlined 160

* complete tests with UInt256 and UInt160

* neo.UnitTests/UT_UIntBenchmarks.cs

* Lights division calculation

* Treat lower hashes as higher priority. Fix MemoryPool UT for Hash order. (neo-project#563)

* Treat lower hashes as higher priority. 
* Fix MemoryPool UT for Hash order.
* Renaming Trasanction in PoolItem for clarity.

* Make PoolItem independent and add PoolItem tests (neo-project#562)

* make poolitem independent

* Merging

* Multiply by -1

* Fix other

* Fix Tx

* Removing -1 extra multiplication

* Fix

* make PoolItem internal and added test class

* Update PoolItem.cs

* added comments for PoolItem variables

* getting time from TimeProvider to allow testing

* basic test

* reset time provider

* Add Hash comparison

* Adding time provider again and equals

* Fix arithmetic

* Comment on PoolItem

* Update PoolItem.cs

* protecting tests against TimeProvider changes on fails

* reusing setup part

* fixed serialization properties

* Improve generation of creating mock DateTime values. Implement hash comparison tests.

* Adjust comment.

* Treat Claim transactions as the highest low priority transactions. (neo-project#565)

* Allow persistence plugins to commit as a final step. (neo-project#568)

* Allow persistence plugins to commit as a final step.

* Plugins commit before core commits, once all plugins have handled initial work OnPersist.

* Allow PersistencePlugin to determine whether to crash if commit fails.

* Add ShouldThrowExceptionFromCommit method to IPersistencePlugin.

* Throw all commit exceptions that should be thrown in an AggregateException.

* Add a Plugin type for observing transactions added or removed from the MemoryPool. (neo-project#580)

* Correctly handle conversions between JSON objects (neo-project#586)

* Fix neo-project/neo-node#297 (neo-project#587)

* Replace new JArray with .ToArray (AccountState) (neo-project#581)

* Ensure `LocalNode` to be stoped before shutting down the `NeoSystem`
txhsl added a commit to txhsl/neo that referenced this pull request Feb 25, 2019
* Handles escape characters in JSON

*  Pass ApplicationExecution to IPersistencePlugin (neo-project#531)

* Update dependencies: (neo-project#532)

- Akka 1.3.11
- Microsoft.AspNetCore.ResponseCompression 2.2.0
- Microsoft.AspNetCore.Server.Kestrel 2.2.0
- Microsoft.AspNetCore.Server.Kestrel.Https 2.2.0
- Microsoft.AspNetCore.WebSockets 2.2.0
- Microsoft.EntityFrameworkCore.Sqlite 2.2.0
- Microsoft.Extensions.Configuration.Json 2.2.0

* change version to v2.9.4

* Updating Unknown to Policy Fail (neo-project#533)

* Fix a dead lock in `WalletIndexer`

* Downgrade Sqlite to 2.1.4 (neo-project#535)

* RPC call gettransactionheight (neo-project#541)

* getrawtransactionheight

Nowadays two calls are need to get a transaction height, `getrawtransaction` with `verbose` and then use the `blockhash`.
Other option is to use `confirmations`, but it can be misleading.

* Minnor fix

* Shargon's tip

* modified

* Allow to use the wallet inside a RPC plugin (neo-project#536)

* Improve Large MemoryPool Performance - Sort + intelligent TX reverification (neo-project#500)

Improve Large MemoryPool Performance - Sort + intelligent TX reverification (neo-project#500)

* Keep both verified and unverified (previously verified) transactions in sorted trees so ejecting transactions above the pool size is a low latency operation.
* Re-verify unverified transactions when Blockchain actor is idle.
* Don't re-verify transactions needlessly when not at the tip of the chain.
* Support passing a flag to `getrawmempool` to retrieve both verified and unverified TX hashes.
* Support MaxTransactionsPerBlock and MaxFreeTransactionsPerBlock from Policy plugins.
* Rebroadcast re-verified transactions if it has been a while since last broadcast (high priority transactions are rebroadcast more frequently than low priority transactions.

* Policy filter GetRelayResult message (neo-project#543)

* Policy filter GetRelayResult message

* adding fixed numbering for return codes

* Removed enum fixed values

* Add some initial MemoryPool unit tests. Fix bug when Persisting the GenesisBlock (neo-project#549)

* More MemoryPool Unit Tests. Improve Re-broadcast back-off to an increasing linear formula. (neo-project#554)

* Ensuring Object Reference check of SortedSets for speed-up (neo-project#557)

* Minor comments update on Mempool class (neo-project#556)

* Update MemoryPool Unit Test to add random fees to Mock Transactions (neo-project#558)

* Add Unit Test for MemoryPool sort order. Fixed sort order to return descending. (neo-project#559)

* Add unit test to verify memory pool sort order and reverification order. Fixed sort order bug.

* VerifyCanTransactionFitInPool works as intended. Also inadvertantly verified GetLowestFeeTransaction() works.

* Benchmark structure for UInt classes (neo-project#553)

* basic benchmark structure for UInt classes

* commented code2 from lights for now

* updated tests. all seem correct now

* Switch to using a benchmark method taking a method delegate to benchmark.

* Make pass.

* 1 million iterations.

* Switch to ulong for the 4th option, and it is still the same speed.

* fix test data for 50% equal data

* make test pass

* neo.UnitTests/UT_UIntBenchmarks.cs

* neo.UnitTests/UT_UIntBenchmarks.cs

* Base 20 - UInt160 tests

* neo.UnitTests/UT_UIntBenchmarks.cs

* inlined 160

* complete tests with UInt256 and UInt160

* neo.UnitTests/UT_UIntBenchmarks.cs

* Lights division calculation

* Treat lower hashes as higher priority. Fix MemoryPool UT for Hash order. (neo-project#563)

* Treat lower hashes as higher priority. 
* Fix MemoryPool UT for Hash order.
* Renaming Trasanction in PoolItem for clarity.

* Make PoolItem independent and add PoolItem tests (neo-project#562)

* make poolitem independent

* Merging

* Multiply by -1

* Fix other

* Fix Tx

* Removing -1 extra multiplication

* Fix

* make PoolItem internal and added test class

* Update PoolItem.cs

* added comments for PoolItem variables

* getting time from TimeProvider to allow testing

* basic test

* reset time provider

* Add Hash comparison

* Adding time provider again and equals

* Fix arithmetic

* Comment on PoolItem

* Update PoolItem.cs

* protecting tests against TimeProvider changes on fails

* reusing setup part

* fixed serialization properties

* Improve generation of creating mock DateTime values. Implement hash comparison tests.

* Adjust comment.

* Treat Claim transactions as the highest low priority transactions. (neo-project#565)

* Allow persistence plugins to commit as a final step. (neo-project#568)

* Allow persistence plugins to commit as a final step.

* Plugins commit before core commits, once all plugins have handled initial work OnPersist.

* Allow PersistencePlugin to determine whether to crash if commit fails.

* Add ShouldThrowExceptionFromCommit method to IPersistencePlugin.

* Throw all commit exceptions that should be thrown in an AggregateException.

* Add a Plugin type for observing transactions added or removed from the MemoryPool. (neo-project#580)

* Correctly handle conversions between JSON objects (neo-project#586)

* Fix neo-project/neo-node#297 (neo-project#587)

* Replace new JArray with .ToArray (AccountState) (neo-project#581)

* Ensure `LocalNode` to be stoped before shutting down the `NeoSystem`
rodoufu pushed a commit to rodoufu/neo that referenced this pull request Mar 5, 2019
* Allow persistence plugins to commit as a final step.

* Plugins commit before core commits, once all plugins have handled initial work OnPersist.

* Allow PersistencePlugin to determine whether to crash if commit fails.

* Add ShouldThrowExceptionFromCommit method to IPersistencePlugin.

* Throw all commit exceptions that should be thrown in an AggregateException.
Thacryba pushed a commit to simplitech/neo that referenced this pull request Feb 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants