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

Fix issues with missing persistence for trade state #4816

Merged

Conversation

chimp1984
Copy link
Contributor

@chimp1984 chimp1984 commented Nov 18, 2020

There are some bug reports which suggest that the persistence at shutdown is not working reliable (hard kill, crash,...).
We reduce the persistence interval radically to ensure important data is written immediately (200 ms delay).
Further the requestPersistence has been missing in most trade tasks. I guess that happened when merging the large refactoring projects (trade protocol, persistence). If shutdown routine gets executed it did not had any effect as we wrote then the trade state, but if that was missing we might miss important trade state/data changes.

Fixes #4806
Fixes #4762

Seems the persistence at shutdown is too unsafe and we got bug reports where data was missing.
bisq-network#4806

Use millisec instead of sec for delay
Rename delayInSec to delay
@jmacxx
Copy link
Contributor

jmacxx commented Nov 18, 2020

This would not resolve #4806 since requestPersistence for PendingTrades is only called twice: when the trade is new, and when the user closes the trade. There was > 12 hours in between where the trade progressed through all its states with no call to requestPersistence.

[EDIT] Ok, I see you're trying to persist in SIGTERM. Maybe it would be ok. If the delay is only 200ms maybe that is enough time before the process is shut down. It wouldn't help in the case of power cut though.

@chimp1984
Copy link
Contributor Author

Oh, yes you are right. I though at trade task complete we call it but I fear that got lost in some merge. It was a bit complicate with several larger PRs (refactoring of trade protocol + refactoring of persistence).
I will check how to fix it best...

We relied on the shutdwon routine to be called reliably but it seems that is not the case as some bug reports show.
So we call requestPersistence at every write access of the trade object
@chimp1984
Copy link
Contributor Author

I added the requestPersistence at each data change in trade. Hope I did not miss any. We could add some redundancy if we call it at the complete() method of each tradeTask but not sure if thats needed.

@chimp1984 chimp1984 changed the title Reduce interval for persistence Fix issues with missing persistence for trade state Nov 18, 2020
@chimp1984
Copy link
Contributor Author

Failing test is resolved by @stejbac (#4789 (comment)). Will merge in once hie PR is merged.

@jmacxx
Copy link
Contributor

jmacxx commented Nov 18, 2020

ACK, tested, fixes #4806.

@chimp1984
Copy link
Contributor Author

I double checked all trade (and sub models) related fields as well as all trade protocol tasks and protocols. Hope I did not miss a call but as there is quite a lot of redundancy I think its safe now.

@sqrrm
Copy link
Member

sqrrm commented Nov 18, 2020

I feel it might be cleaner to do the persist in the complete() method at the end of each trade task. It feels like that's what's being done with this PR anyway, but separately in each task with the chance of missing it somewhere.

Apart from that I think this looks ok and could be merged.

@chimp1984
Copy link
Contributor Author

I feel it might be cleaner to do the persist in the complete() method at the end of each trade task. It feels like that's what's being done with this PR anyway, but separately in each task with the chance of missing it somewhere.

Apart from that I think this looks ok and could be merged.

I was wondering myself if we should add at the tradeTask complete handler a perist call. It would add extra redundancy in case I missed one as well in case we add some tasks or have some changes and the call is forgotten.
I have no strong opinion for or against it. Signal with up or downvote if you want to have it in.

We get called some setter methods from protobuf methods before tradeManager is set.
The deposit confirmed state is set after we applied the mailbox messages,
which led to a task failure due wrong phase and the message was not applied.
Further it can be that the wallet is still syncing and the deposit
confirmed state is set in any time in the future.

To fix the first problem we add a bit of delay so that the trade has
been updated when we apply the mailbox messages. A better fix would be to change
the order of the methods but that is a bit tricky to get right and I dont want to
risk that for that release.

The second problem would require a large change to trigger the mailbox
processing based on wallet state. We prefer to be more tolerant with
the expected phase instead so allow the mailbox message to be processed
also in the DEPOSIT_PUBLISHED state.
This has no risks as the payout tx would be invalid anyway if the
buyer has cheated and sent the msg in not confirmed deposit tx state (only
possible with code manipulation).

A better fix would to add a listener for the wallet and process
the mailbox msg once wallet is ready and trade state set, but I
leave that for another PR.
@ripcurlx ripcurlx added this to the v1.5.0 milestone Nov 19, 2020
This is not really needed as we call it at each state change of the
trade but gives more redundancy in case we missed one or once
changes are applied and a dev forgets to call it.

Multiple repeated calls do have close to zero costs.
We need to set addDecryptedDirectMessageListener without
delay as otherwise we could miss direct messages (detected
with localhost testing, with tor its likely slower and
would not have been triggered).
@ripcurlx ripcurlx merged commit ce265e4 into bisq-network:release/v1.5.0 Nov 19, 2020
@sqrrm
Copy link
Member

sqrrm commented Nov 19, 2020

With the persistence call in complete() it's not necessary to persist in each trade task.

@chimp1984
Copy link
Contributor Author

With the persistence call in complete() it's not necessary to persist in each trade task.

A reason why I did not do want to rely only on complete is as there are async tasks and i want to be sure that if the task never completes (shutdown) that the intermediate state change is persisted. But also not happy that its that verbose now ;-(. But its more similar as it was before, just that some calls have been done inside the trade setter methods.

@sqrrm
Copy link
Member

sqrrm commented Nov 19, 2020

Agreed that some persist calls should still be done in the tasks, but all of those done synchronously just before complete() are no longer needed.

@chimp1984 chimp1984 deleted the reduce-persistence-interval branch November 19, 2020 18:04
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