-
-
Notifications
You must be signed in to change notification settings - Fork 142
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
feat: add a way to cache state between restarts of Neovim #624
feat: add a way to cache state between restarts of Neovim #624
Conversation
This is useful for features such as `org-clock-in-last` that has the ability to persist its "knowledge" of the last clocked in task. Org mode does this by saving to a cache file on system. This commit gives nvim-orgmode the same capability.
9b2b087
to
7106e2e
Compare
@kristijanhusak I'm primarily interested in what you think. If the above all sounds good and the code looks solid, I intend to get this merged and then turn around and implement at least |
Thanks for the PR. I didn't give it a deeper look yet. I have one question regarding this:
Can you point me where I can read more about this? I wasn't aware it is done in Emacs, at least not in this way. I assumed Emacs has a more advanced persistence. |
So emacs is a little bit fancier than the method done above to persist state. That
Which definitely is more complex than what I'm implementing here. See here for some details in the manual as to clocking in with persistence. Trying to find a more specific manual currently. |
Found it, source code for Or you can directly get it by cloning from Savannah, |
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.
I didn't give it a test, but I did review the code.
Generally, it looks ok but I need to investigate a bit more to see what and how we should persist data.
Also, it would be great to write some tests around this to ensure it works as expected.
Absolutely. I just wanted to check that this looked good in the first place before writing up tests etc. only to be told that it's a no go. I'll get those tests written after resolving your comments in a sec here. |
No need to do `vim.tbl_deep_extend`. kristijanhusak Nov 2, 2023: > Doing this should be enough, since nil is considered a falsy value. Co-authored-by: Kristijan Husak <[email protected]>
Since we instantly attempt to repair the State file by saving it, the `decoded` variable can be set again to the correct value. As such, we need to take a copy of the value to ensure it doesn't get overriden by the next load operation.
Instead of using `Promise.next`, it's preferred to use the `catch` and `finally` functions provided by Orgmode's Promise library. See nvim-orgmode#624 (comment) > Handle the errors through the `:catch` function instead of 2nd param to `:next`. > > ```lua > utils.writefile(cache_path, vim.json.encode(State.data)):catch(function(err_msg) > vim.schedule_wrap(function() > vim.notify('Failed to save current state! Error: ' .. err_msg, vim.log.levels.WARN, { title = 'Orgmode' }) > end) > end) > ```
See nvim-orgmode#624 (comment) > You can just return `Promise.resolve()` here.
This change makes it easier to test. To use the state module a downstream caller must now do "require('orgmode.state.state')()".
6ab1217
to
4ebb84b
Compare
Still need to write a test for the self-healing. |
As a heads up @kristijanhusak this should be good to go. If you're happy with this, I'm going to begin implementing some missing orgmode features that can use persistence. |
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.
We're almost there, just few minor changes and it's good to go.
9094379
to
abff0dc
Compare
See nvim-orgmode#624 (comment) > Since this is a singleton we should return the instance of it here `return State.new()`
See nvim-orgmode#624 (comment) > Move this also to a :catch so it is consistent with other error handlers in the file.
See nvim-orgmode#624 (comment) Co-authored-by: Kristijan Husak <[email protected]>
@kristijanhusak Let me know if you see anything else. |
@treatybreaker how did you test this manually? vim.keymap.set('n', '<leader>u', function()
local state = require('orgmode.state.state')
return state:load():finally(function()
print('LOADED', state.data)
state.field = 'value'
state:save()
end):next(function()
print('SAVED')
vim.print('UPDATED STATE', state.data)
end)
end) Prints are never shown, and -- This passes, even though it shouldn't
assert.are.equal(state.my_var, 'hello world foo') Something seems to be off. Can you check? Thanks. |
All tests should work as expected now.
0f8b807
to
056191f
Compare
This was uhhh, painful. Async code in lua is the very definition of not fun. I think this should be good now, I have the tests responding correctly now by abusing I am really hoping this is good at this point. If it's not then I'm going to keep on grinding until it's in a good state. Take a look and let me know your findings. |
As a note, Neovim didn't seemingly create those |
Awesome, now it works :)
|
8a601b6
to
414e8d0
Compare
Added those functions as well as a Man... async code and multiple execution is hell on earth. Very useful, but my god. Looking forward to more hellish findings 😉. |
It's possible to have multiple save operations happening at once. We only want to declare the context as "saved" when all savers are finished.
923416e
to
d74f13b
Compare
Working on replicating the failure in |
Fixed. |
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! Just some minor tweaks to types and tests and it's good to go.
See nvim-orgmode#624 (comment) Co-authored-by: Kristijan Husak <[email protected]>
See nvim-orgmode#624 (comment) See nvim-orgmode#624 (comment) See nvim-orgmode#624 (comment) Co-authored-by: Kristijan Husak <[email protected]>
See nvim-orgmode#624 (comment) Co-authored-by: Kristijan Husak <[email protected]>
Let me know if you see anything else 🙂 |
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.
Ok, everything looks great now, thanks!
I'll look into implementing some features that take advantage of this come this weekend or next week as a heads up. |
…de#624) Co-authored-by: Kristijan Husak <[email protected]>
This is useful for features such as
org-clock-in-last
that has the ability to persist its "knowledge" of the last clocked in task. Org mode does this by saving to a cache file on system. This commit givesnvim-orgmode
the same capability.I'm creating this PR in what I consider a partially finished state. I'm primarily looking for feedback as to the design of this module. In the scenario we're all happy with the design then I can get some simple tests written and then promote this to a non draft PR.
Some quick notes:
nvim-orgmode
bundles. This means there's some additional validation and steps taken than what might exist in fully synchronous code.State
table in which we assign new values are saved into the subtabledata
. This is so later on it is easy to determine what to save into the cache. Without it, I'd have to write additional logic explicitly excluding specific keys from theState
table.State
object is a singleton is may seem weird to bother with aState:new()
function. This actually is quite important, this sets up the metatable after all other functions are read in the file, ensuring they are not bound to thedata
subtable within theState
object.vim.fs.normalize
.Any feedback (especially critical feedback) is desired on this. I'm looking to iron out kinks and find out if this is even desired 😃.