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

Remote store #59

Merged
merged 8 commits into from
Jul 24, 2020
Merged

Remote store #59

merged 8 commits into from
Jul 24, 2020

Conversation

sorki
Copy link
Member

@sorki sorki commented Mar 5, 2020

Summary

  • restores most functionality and tests
  • adds proper path parsing and quickcheck props
  • drops TypeLits and symbolic store path root
  • includes Base16/Base32 decoding, props/tests  #57 (please comment on Base32 there) and Add makeFixedOutputPath #36 so this can be tested easily as a whole
  • addToStoreNar now works and has a test
  • drops regex-tdfa, uses simpler solution, original regex wouldn't roundtrip and it was the only use of regex-tdfa

The reason for dropping symbolic StoreDir is that knowing path at compile time seems too restrictive and prevents us working with any store root (as the test do - tests run namespaced and create and-hoc store in temporary directory not to interfere with systems nix store). Maybe there is a way to have this level of type safety on top of store implementations but making them part of StorePath complicates things quite a lot. If anyone see a better solution I'm open to ideas.

Can also split this into multiple commits if that would be better.

@sorki
Copy link
Member Author

sorki commented Mar 5, 2020

@sorki sorki mentioned this pull request Mar 5, 2020
Copy link
Contributor

@layus layus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whaaaow ! An impressive piece of work. Just nitpicks for now, but I will definitely try it later.

hnix-store-remote/src/System/Nix/Store/Remote.hs Outdated Show resolved Hide resolved
Copy link

@stolyaroleh stolyaroleh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 - I like the simpler StorePath type.

addToStore name pth recursive algoProxy pfilter repair = do

-- TODO: Is this lazy enough? We need `B.putLazyByteString bs` to stream `bs`
bs :: BSL.ByteString <- liftIO $ B.runPut . putNar <$> localPackNar narEffectsIO pth

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to use a streaming library here (so that adding files or consuming logs incrementally uses the same mechanism)?

Copy link
Member Author

@sorki sorki Mar 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, even NARs needs streaming library (#51).

hnix-store-remote/src/System/Nix/Store/Remote.hs Outdated Show resolved Hide resolved
Copy link
Contributor

@layus layus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this is great work. Thanks !

Putting typed store paths aside is a wise move. We can still reintroduce them later on if we feel so.

hnix-store-core/src/System/Nix/Internal/Base32.hs Outdated Show resolved Hide resolved
Comment on lines 111 to 124
makeStorePathName :: Text -> Either String StorePathName
makeStorePathName n = case validStorePathName n of
True -> Right $ StorePathName n
False -> Left $ reasonInvalid n

reasonInvalid n | n == "" = "Empty name"
reasonInvalid n | (T.length n > 211) = "Path too long"
reasonInvalid n | (T.head n == '.') = "Leading dot"
reasonInvalid n | otherwise = "Invalid character"

validStorePathName "" = False
validStorePathName n = (T.length n <= 211)
&& T.head n /= '.'
&& T.all validChar n
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make sense to merge the three functions into one. Such as to avoid duplication of all the conditions. Then validStorePathName = isRight . makeStorePathName.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I think I was going to use validStorePathName with Arbitrary but decided against that.

hnix-store-remote/src/System/Nix/Store/Remote/Util.hs Outdated Show resolved Hide resolved

next <- go decoder
return $ next

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "async read" part of the protocol looks really weird. Any idea why it was implemented like that in the daemon ?

hnix-store-remote/tests/NixDaemon.hs Outdated Show resolved Hide resolved
hnix-store-remote/src/System/Nix/Store/Remote/Protocol.hs Outdated Show resolved Hide resolved
@domenkozar
Copy link
Contributor

cc @shlevy would be amazing if you can take a look at this.

Copy link
Contributor

@layus layus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

I have finally finished my prim_derivationStrict implementation based on your PR. It wokrs perfectly well for writing derivations, generating store paths and fixedOutput store paths, and reading the derivations.

I did not test the building part about getting the build result and triggering builds.

However I think this PR is quite ready to merge, and should not be delayed for too long. Types seem consistent. Further fixes to the implementation can be added later on. What do you think ?

@sorki
Copy link
Member Author

sorki commented May 10, 2020

@layus Nice! Can you point me to the prim_derivationStrict impl? I've recently PRed Gabriella439/Haskell-Nix-Derivation-Library#4 that should make integrating nix-derivation into this lib quite easy regarding reuse of StorePath. If you're on IRC we are now on #hnix channel as well, might bridge the gitter hnix channel with that at some point. Would make coordination easy if you can join.

I also have few changes pending from yesterday to this PR but nothing that should clash with your commits it seems.

@sorki
Copy link
Member Author

sorki commented May 10, 2020

Fixed usage of obsolete ValidPath which was replaced by StorePathMetadata. Also changed a type of addToStore to accept hash typed pun, removed redundant Proxy and changed pathFilter type to (FilePath -> Bool) although it is unused for now.

@layus
Copy link
Contributor

layus commented May 10, 2020

There is a big pain point with path filters in the sense that they are generally nix functions to be evaluated inside MonadNix, which itself relies on the store. Is there a way to cope with this circular dependency ?

buildDerivation p drv buildMode = do
runOpArgs BuildDerivation $ do
putPath p
putDerivation drv
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This design decision bugs me in the nix protocol. At that point, the .drv is already present in the store. Why not provide a buildDerivation(/nix/store/xxx.drv) ? I guess the reason is about garbage collection and such, but still. What is the point of writing .drv's to the store then ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or rather, why do we have to upload both the path and the drv itself ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, I found the wopBuildPaths that does exactly that. wopBuildDerivation is pretty specific for "anonymous" builds and was introduced for hydra in NixOS/nix@1511aa9

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the commit link. I was a bit confused about that as well.

-- XXX: reason for this is unknown
-- but without it protocol just hangs waiting for
-- more data. Needs investigation
putInt 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only thing I could see is that libstore has a flush() operation. But possibly it's just putEnum that is not up to the task.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might be right about putEnum since it's the only use of it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't make much sense either, putEnum is just putInt . fromEnum so it's more like missing field. I don't care that much at this point as I'm playing with local store and daemon impl. so I'll be able to end-to-end test this without nix-daemon and the reason will probably become clear.

@sorki
Copy link
Member Author

sorki commented May 29, 2020

  • rebased
  • added few docstrings
  • cleaned-up imports
  • added parsing and building of ContentAddressableAddresses

StorePathMetadata signatures need bit more legwork (extracting public keys from nix.conf). Marking this as ready for review as I'm quite happy with it now.

@sorki sorki marked this pull request as ready for review May 29, 2020 13:04
@sorki
Copy link
Member Author

sorki commented May 29, 2020

There is a big pain point with path filters in the sense that they are generally nix functions to be evaluated inside MonadNix, which itself relies on the store. Is there a way to cope with this circular dependency ?

@layus I think that proper use of effects and possibly introducing a library like polysemy might allow us to resolve this and metadata caching as well. I'll open an issue for discussing this separately with the PoC I wrote recently.

@sorki
Copy link
Member Author

sorki commented Jun 12, 2020

Further improvements to currently too sha256 specific parsers require 0099f6d from #64 which depends on this.

@sorki
Copy link
Member Author

sorki commented Jun 12, 2020

Added Closes clause referencing relevant issues.

@sorki
Copy link
Member Author

sorki commented Jun 28, 2020

I'll do one final pass over this, add changelog for -remote, changelog entries for -core, split a testsuite a bit and merge this during the next week if there are no objections.

sorki added 8 commits July 14, 2020 13:27
Disabled by default since it requires `nix-daemon` binary
and Linux namespaces support.

For development this can be enabled by

```
cabal configure --flag=io-testsuite
```

or by adding

```
flags: +io-testsuite
```

to `cabal.project.local`

Enabled by `callCabal2nixWithOptions` in `overlay.nix` so
it is tested by `nix-build` and `nix-shell` brings all
test dependencies.

This is fine on NixOS where `build-tool-depends: nix:nix-daemon` works
and we have namespaces supported.
@sorki
Copy link
Member Author

sorki commented Jul 14, 2020

ChangeLogs done, added dff7527 which puts hnix-store-remote testsuite behind a flag so we don't run into problems on non-NixOS systems.

Final pass hopefully, leaving open for few more days if anyone wants to chime in.

@sjakobi
Copy link
Member

sjakobi commented Jul 14, 2020

@sorki Where can I find out more about the context and goal of this work?

Apparently this fixes addresses #22?

Is there any more information on what hnix-store-remote is than the bit in https://github.com/haskell-nix/hnix-store/tree/master/hnix-store-remote#hnix-store-remote?

Apologies if this is not a good place for these questions! I'm just a bit curious.

@sorki
Copy link
Member Author

sorki commented Jul 14, 2020

@sorki Where can I find out more about the context and goal of this work?

This is mostly an adaptation of previous work to changes in core that were added to support the remote part, except for dropping symbolic StoreDir which proved difficult to work with and in the end not that important due to gradual move to store root independent Nix stores.

Few missing bits were added as well, especially

  • parsing for StorePaths
  • integration of nix-derivation that uses our StorePath type

Currently the goal is to allow interacting with nix-daemon via so called remote protocol and provide interface for hnix, so the calls to nix-instantiate and nix-store --add can be migrated to this (like haskell-nix/hnix#554 which this PR should make a bit easier).

Apparently this fixes addresses #22?

I hope but the description is too vague :)

Is there any more information on what hnix-store-remote is than the bit in https://github.com/haskell-nix/hnix-store/tree/master/hnix-store-remote#hnix-store-remote?

Part of https://github.com/haskell-nix/hnix-store#rationale is good overview, now when you asked you reminded me it needs an update to reflect the current state since remote is fully functional now (Rationale calls it daemon but it's a client to existing nix-daemon).

@sorki sorki merged commit 59e08d4 into haskell-nix:master Jul 24, 2020
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.

7 participants