-
Notifications
You must be signed in to change notification settings - Fork 2
feat: Add support for batch delete #78
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
base: master
Are you sure you want to change the base?
Conversation
| return failure(err.msg) | ||
| return success() | ||
| method delete*(self: LevelDbDatastore, keys: seq[Key]): Future[ | ||
| ?!void] {.async.} = |
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.
🟡 This comment is likely beyond the scope of this PR, but we need to address this at some point (probably in a separate PR). I know you were amending what was already there, so definitely not something you have done. This is more for general information.
We should always try to annotate async pragmas with raises to inform the compiler and callers of potential exceptions that can be raised. This is useful so that callers can distinguish between exceptions being raised in a try/except block and potentially perform different operations depending on which exception was raised, eg
try:
await key.read()
await key.delete()
key.removeFromListOfKeysToDelete()
except ReadError as e:
# already doesn't exist, remove from deletion list
key.removeFromListOfKeysToDelete()
except DeleteError as e
# failed to delete, keep on deletion list, but may keep happening
error "failed to delete", error = e.msgis much more informative than:
try:
await key.read()
await key.delete()
key.removeFromListOfKeysToDelete()
except CatchableError as e:
# here we don't know which module raised the exception, and can only tell by inspecting the error message
if "read failed" in e.msg:
# already doesn't exist, remove from deletion list
key.removeFromListOfKeysToDelete()
elif "delete failed" in e.msg:
# failed to delete, keep on deletion list, but may keep happening
error "failed to delete", error = e.msg
else:
error "unknown error", error = e.msgHowever, the operations in this module use return failure("some string") which returns a CatchableError instead of a module-specific and operation-specific exception, which means that the signatures in this module would simply have {.async: (raises: [CatchableError]).}. This does not give the caller much flexibility, where their only choice is wrap the calls in a try/except CatchableError and distinguish which exception was raised based on the error message.
So, we should be aiming to have module-specific errors as a base, and operation-specific errors as the raised exception, ie
type
LevelDbDatastoreError = object of DatastoreError
LevelDbReadError = object of LevelDbDatastoreError
LevelDbDeleteError = object of LevelDbDatastoreError
method delete*(self: LevelDbDatastore, key: Key): Future[?!void] {.async: (raises: [LevelDbDeleteError]).} =
try:
#...
except LevelDbException as e:
return failure newException(LevelDbDeleteError, "LevelDbDatastore.delete batch exception: " & e.msg, e)This allows callers the flexibility to handle all exceptions from the module with eg try/except LevelDbDatastoreError, or operation-specific exceptions, eg try/except LevelDbDeleteError.
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.
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.
Sorry, I misspoke a bit earlier. Since we're returning a Result which captures the exceptions, the raises pragma should only raise CancelledError, but the remainder of what I described should work.
No description provided.