-
Notifications
You must be signed in to change notification settings - Fork 4
Automatically repair torn writes on opening #155
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
Conversation
|
Torn writes always coincide with a still locked writer. This can currently only be unlocked with an explicit |
src/Storage/WritableStorage.js
Outdated
| if (!this.lock()) { | ||
| return true; | ||
| } | ||
| this.checkTornWrites(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this here is a waste, because in most cases there was no previously failed write.
This check should only happen when a lock still exists, but is reclaimed. That in turn can only happen when:
- the user explicitly forces the reclaiming (e.g. by a constructor option)
- the previous lock has "timed out"
Regarding timing out the lock, a possible way to do this sensibly is this (see proper-lockfile):
- touch the lock file every X timeframe (to update mtime)
- when opening, check if the lock is at least 2*X "old" and if so, reclaim it
Only checking if the lock is X time old without touching it would cause trouble with long running applications. Touching the lock every X time is additional work. So if implemented this way, this auto-reclaiming needs to be optional.
For the manual reclaiming, the API needs to be reconsidered:
try {
eventstore = new EventStore(...);
} catch (EventStoreLockedError e) {
eventstore = new EventStore(..., { forceLock: true });
}wrapping class instanciation in a try/catch is awkward at best and if the reclaiming is known to be safe at instanciation time this can always be reduced to eventstore = new EventStore(..., { forceLock: true }); anyway.
eventstore = new EventStore(..., { lock: EventStore.LOCK_AUTO, lockTimeout: 60 }); // Use lock dir with timeout (60s), reclaim+repair if timed out
eventstore = new EventStore(..., { lock: EventStore.LOCK_FORCE }); // Always take the lock, reclaim+repair if lock exists
eventstore = new EventStore(..., { lock: EventStore.LOCK_MANUAL }); // Throw if an second instance is created, needs manual intervention (delete lock) after a crash
Right now the behaviour is LOCK_MANUAL. What would be a good default once the other methods are implemented? Depends on the use-case - LOCK_FORCE is the least safe, LOCK_MANUAL is safest but hard to fix on error and LOCK_AUTO is the dont-make-me-think mode
This change checks the storage for torn writes when force unlocking and truncates all partitions (and indexes) to the last valid write. After a crash, this can be done by doing the following (once):
Related to #31 and #107