You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When syncing from a local archive directory it seems like cabal-cache sync-from-archive does not sync libraries that are contained in the ${archive_version}/${store_hash} sub-folder even if the store hash for the store to sync to coincides with store_hash.
What and why?
Using cabal-cache in a CI/CD setup to avoid having to rebuild all dependencies, we encountered a number of cache-misses for dependencies that were contained in the (store-hash subfolder of the) archive. This did not make the builds fail. However, the corresponding dependencies had to be rebuilt which increased build times.
Notably, we encountered lines such as the following even though the package was contained in the archive and the store hashes coincide:
Not found: Local "cabal-cache/v2/ghc-9.4.8/colour-2.3.6-e74462c0ef939bc168bf448e20d49ad726c72b5868b56e583db62c85090062d2.tar.gz" :| [Local "cabal-cache/v2/fcfe93a36b/ghc-9.4.8/colour-2.3.6-e74462c0ef939bc168bf448e20d49ad726c72b5868b56e583db62c85090062d2.tar.gz"]
...
Failed to download: colour-2.3.6-e74462c0ef939bc168bf448e20d49ad726c72b5868b56e583db62c85090062d2
...
It was possible to reproduce the problem locally.
Steps to reproduce (locally)
Create a cabal project (ideally small to avoid long build times) with at least one dependency whose build artifact contains absolute paths to the cabal store. For us (ghc-9.4.8) colour-2.3.6 was one such dependency.
Set store path in cabal.project.local to some absolute path, e.g., store-dir: /tmp/.cabal-store/ (this step is optional but it helps to avoid messing with the default store).
Build the project, respectively its dependencies: cabal build --dependencies-only
Sync store to archive: cabal-cache sync-to-archive --archive-uri my-archive --store-path /tmp/.cabal-store.
At this point a folder my-archive with the following sub-folder structure should have been created:
Sync store from created archive: cabal-cache sync-from-archive --archive-uri my-archive --store-path /tmp/.cabal-store
Expected behavior
After syncing from the archive, the store should contain exactly the same library artifacts as before. Invoking cabal build --dependencies-only again should not rebuild anything.
Actual behavior
cabal-cache sync-from-archive encounters cache misses for all dependencies that are contained in the store_hash sub-folder of the cache:
Not found: Local "cabal-cache/v2/ghc-9.4.8/colour-2.3.6-e74462c0ef939bc168bf448e20d49ad726c72b5868b56e583db62c85090062d2.tar.gz" :| [Local "cabal-cache/v2/fcfe93a36b/ghc-9.4.8/colour-2.3.6-e74462c0ef939bc168bf448e20d49ad726c72b5868b56e583db62c85090062d2.tar.gz"]
...
Failed to download: colour-2.3.6-e74462c0ef939bc168bf448e20d49ad726c72b5868b56e583db62c85090062d2
...
Checking the store indicates that colour was not synced down and invoking cabal build --dependencies-only again yields:
Build profile: -w ghc-9.4.8 -O1
In order, the following will be built (use -v for more details):
- alex-3.5.1.0 (exe:alex) (requires build)
- byteable-0.1.1 (lib) (requires build)
- colour-2.3.6 (lib) (requires build)
...
Suspects
It seems like the issue comes from HaskellWorks.CabalCache.IO.Lazy.readFirstAvailableResource. This function takes a non-empty list of the two possible locations to search for a library artifact. To do so it invokes HaskellWorks.CabalCache.IO.Lazy.readResource for the first location. This function throws NotFound if the artifact is located in the store_hash folder. In this case readFirstAvailableResource is not prepared to handle NotFound which means that the second location (which contains the store-hash) is never looked at.
Handling NotFound the same way as AwsError and HttpError are handled seems to fix the issue:
diff --git a/src/HaskellWorks/CabalCache/IO/Lazy.hs b/src/HaskellWorks/CabalCache/IO/Lazy.hs
index de4360c..13c7adf 100644
--- a/src/HaskellWorks/CabalCache/IO/Lazy.hs
+++ b/src/HaskellWorks/CabalCache/IO/Lazy.hs
@@ -105,6 +105,10 @@ readFirstAvailableResource :: ()
-> ExceptT (OO.Variant e) m (LBS.ByteString, Location)
readFirstAvailableResource envAws (a:|as) maxRetries = do
(, a) <$> readResource envAws maxRetries a
+ & do OO.catch @NotFound \e -> do
+ case NEL.nonEmpty as of
+ Nothing -> OO.throwF (Identity e)
+ Just nas -> readFirstAvailableResource envAws nas maxRetries
& do OO.catch @AwsError \e -> do
case NEL.nonEmpty as of
Nothing -> OO.throwF (Identity e)
After installing a local version that contains the change above, cabal-cache synced everything down from the archive as expected and no dependencies had to be rebuilt.
The text was updated successfully, but these errors were encountered:
I was not sure about the PR-policies for this repo (and also about possible side-effects of the change suggested above) which is why I have not opened a PR. I am happy to do so if you agree that the described issue should be fixed and this is the way to do it 😃?
Issue
When syncing from a local archive directory it seems like
cabal-cache sync-from-archive
does not sync libraries that are contained in the${archive_version}/${store_hash}
sub-folder even if the store hash for the store to sync to coincides withstore_hash
.What and why?
Using cabal-cache in a CI/CD setup to avoid having to rebuild all dependencies, we encountered a number of cache-misses for dependencies that were contained in the (store-hash subfolder of the) archive. This did not make the builds fail. However, the corresponding dependencies had to be rebuilt which increased build times.
Notably, we encountered lines such as the following even though the package was contained in the archive and the store hashes coincide:
It was possible to reproduce the problem locally.
Steps to reproduce (locally)
colour-2.3.6
was one such dependency.cabal.project.local
to some absolute path, e.g.,store-dir: /tmp/.cabal-store/
(this step is optional but it helps to avoid messing with the default store).cabal build --dependencies-only
cabal-cache sync-to-archive --archive-uri my-archive --store-path /tmp/.cabal-store
.my-archive
with the following sub-folder structure should have been created:/tmp/.cabal-store
.cabal-cache sync-from-archive --archive-uri my-archive --store-path /tmp/.cabal-store
Expected behavior
After syncing from the archive, the store should contain exactly the same library artifacts as before. Invoking
cabal build --dependencies-only
again should not rebuild anything.Actual behavior
cabal-cache sync-from-archive
encounters cache misses for all dependencies that are contained in thestore_hash
sub-folder of the cache:Checking the store indicates that
colour
was not synced down and invokingcabal build --dependencies-only
again yields:Suspects
It seems like the issue comes from
HaskellWorks.CabalCache.IO.Lazy.readFirstAvailableResource
. This function takes a non-empty list of the two possible locations to search for a library artifact. To do so it invokesHaskellWorks.CabalCache.IO.Lazy.readResource
for the first location. This function throwsNotFound
if the artifact is located in thestore_hash
folder. In this casereadFirstAvailableResource
is not prepared to handleNotFound
which means that the second location (which contains the store-hash) is never looked at.Handling
NotFound
the same way asAwsError
andHttpError
are handled seems to fix the issue:After installing a local version that contains the change above, cabal-cache synced everything down from the archive as expected and no dependencies had to be rebuilt.
The text was updated successfully, but these errors were encountered: