-
Notifications
You must be signed in to change notification settings - Fork 0
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
Implementation of a monadic cursor API. #1
Conversation
d4dff00
to
78d8c59
Compare
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.
Looks good to me. However, shouldn't we delete these functions as we are redefining them here?
And why would one ever run the cursor in IO directly as opposed to running it in a Transaction
?
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.
Nice. Some comments:
- Why not submitting this to the project we forked from? We might get more feedback.
- Why do we need to depend on CBOR, as opposed to (de)serializing in the way
lmdb-simple
used to do it? - I think we should add tests, and optionally some micro-benchmarks.
- It'd be useful to add some (pseudo)doctests that illustrate how the new functions can be used.
However, the forEach function reads a full database, whereas we are only interested in a range of keys in a database.
Is this the only reason why we're introducing this change?
I tried as you suggested, but some functions in the
If one does not want the bracketing behaviour because they want to provide/reuse their own cursor pointer/ |
Good idea, though I would probably expand the API to cover the full cursor functionality if we were to do this. One obstacle is that the original package does not seem to be maintained anymore..
I'll look into this
The primary motivation was to define a cursor fold that folds only over a range and not the full database. However, I did think it would be useful to define a higher-level API for cursors (instead of just writing a lower-level fold without the monadic API) |
5001340
to
83f8415
Compare
I don't think we want to provide |
We're relying on
|
So can we keep on using this approach? I'm afraid we're breaking the uniformity of the LMDB interface. It seems to me we either change all the functions to use That said I don't oppose merging this PR as is. |
I have some ideas on how to unify the |
122392a
to
a410982
Compare
823b5ba
to
04da2fc
Compare
Update: since the last review round, I've focused on three main improvements, and they should be nearly ready for another review round.
|
ed3bf4a
to
9f7f956
Compare
* Extended the API with `put` and `del` operations. * Most of the ops/flags are now handled by the API. Note: some ops and flags require databases to be opened with specific flags like `MDB_DUPSORT`. These ops and flags are not yet supported. * `cborg`-based API is now `serialise`-based. * Cursor operations are now generalised over any monad instead of just `CursorM`.
3220b9d
to
7544c98
Compare
-> LockstepAction (CursorState k v) a | ||
-> ModelValue (CursorState k v) a | ||
-> [Tag] | ||
tagCursorAction _ _ _ = [] |
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.
The tests have no tags yet. Suggestions for sensible tags are welcome! One minimal example I can think of is a simple "round trip": putting, getting and deleting a key.
|
||
main :: IO () | ||
main = defaultMain $ testGroup "test-cursors" [ | ||
testGroup "Test" [ |
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.
Regarding my "bench/Bench" question, here we see that we only have one "test" level. Whatever we pick maybe we should be consistent.
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.
See #1 (comment)
While working on IntersectMBO/ouroboros-network#3954, it became apparent that we need better access to cursors in order to solve a bug with LMDB range reads. This bug resulted from using the
forEach
function to perform reads of ranges of keys. However, theforEach
function reads a full database, whereas we are only interested in a range of keys in a database.This PR provides a small, monadic API to cursors. The API hides the lower-level details of using cursors behind a state-like monad. For example, the
getc
function is similar to theget
function forState
-monads. A specialised version of a customfoldM
is used to read a range of keys. Note that:IO
, or as aTransaction
. The preferred way is to run the cursor as a transaction, because it akin to running the lower-level cursor actions inIO
usingbracket
: the cursor is opened before running all the cursor operations, and it is closed when those have finished.Serialise
type class to serialise/deserialise keys and values. Instead, we use a record-of-functions type calledCodec
. We reimplement theserialise
anddeserialise
functions from theSerialise
library to fit this style.As an additional change, I've updated the
.gitignore
file to include the default entries from https://github.com/github/gitignore/blob/main/Haskell.gitignore. I have also added acabal.project
file.Related PR: input-output-hk/haskell-lmdb#4
Updates
#1 (comment)