Skip to content

Commit 3d63a26

Browse files
authored
Add refresh flag to force refresh of the Registry state (#1372)
1 parent c195ecb commit 3d63a26

File tree

8 files changed

+88
-30
lines changed

8 files changed

+88
-30
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,16 @@ The transfer procedure is automated by Spago commands, and goes as follows:
11421142
The `-v` flag will print out all the `purs` commands that `spago` invokes during its operations,
11431143
plus a lot of diagnostic info, so you might want to use it to troubleshoot weird behaviours and/or crashes.
11441144

1145+
### Force a registry refresh
1146+
1147+
Spago caches the Registry Index for 15 minutes. If you need a package that was just published, you can force a refresh:
1148+
1149+
```console
1150+
$ spago install --refresh some-new-package
1151+
```
1152+
1153+
The `--refresh` flag works with any command that accesses the Registry (`install`, `build`, `fetch`, etc.).
1154+
11451155
### Install autocompletions for `bash`
11461156

11471157
You can just add this to your `.bashrc`:

bin/src/Flags.purs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,30 @@ noColor =
135135
<> O.help "Force logging without ANSI color escape sequences"
136136
)
137137

138-
offline :: Parser OnlineStatus
139-
offline =
138+
offlineFlag :: Parser OnlineStatus
139+
offlineFlag =
140140
O.flag
141141
Online
142142
Offline
143143
( O.long "offline"
144144
<> O.help "Do not attempt to use the network. Warning: this will fail if you don't have the necessary dependencies already cached"
145145
)
146146

147+
refreshFlag :: Parser Boolean
148+
refreshFlag =
149+
O.switch
150+
( O.long "refresh"
151+
<> O.help "Force refresh of the Registry, bypassing the cache"
152+
)
153+
154+
offline :: Parser OnlineStatus
155+
offline = combineOfflineRefresh <$> offlineFlag <*> refreshFlag
156+
where
157+
combineOfflineRefresh offlineStatus refresh = case offlineStatus, refresh of
158+
Offline, _ -> Offline
159+
_, true -> OnlineRefreshRegistry
160+
_, false -> offlineStatus
161+
147162
json :: Parser Boolean
148163
json =
149164
O.switch

src/Spago/Prelude.purs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,18 @@ import Spago.Path as Path
4646
import Spago.Paths as Paths
4747
import Unsafe.Coerce (unsafeCoerce)
4848

49-
data OnlineStatus = Offline | Online | OnlineBypassCache
49+
-- | Controls network/caching behavior for registry operations.
50+
-- | - `Offline`: Never use network, fail if data not cached locally
51+
-- | - `Online`: Normal mode with 15-minute cache for registry data
52+
-- | - `OnlineRefreshRegistry`: Force refresh of registry repos (bypasses 15-min staleness
53+
-- | check), but AVar cache still works normally. Used for `--refresh` flag.
54+
-- | - `OnlineBypassCache`: Bypass ALL caches (process AVar + DB). See usage
55+
-- | in `Spago.Command.Registry.transfer` for details on when this is appropriate.
56+
data OnlineStatus
57+
= Offline
58+
| Online
59+
| OnlineRefreshRegistry
60+
| OnlineBypassCache
5061

5162
derive instance Eq OnlineStatus
5263

src/Spago/Registry.purs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,9 @@ getRegistryFns registryBox registryLock = do
172172
-- we keep track of how old the latest pull was - if the last pull was recent enough
173173
-- we just move on, otherwise run the fibers
174174
{ db, offline } <- ask
175-
fetchingFreshRegistry <- shouldFetchRegistryRepos db
175+
fetchingFreshRegistry <- shouldFetchRegistryRepos offline db
176176
-- we also check if we need to bypass this cache (for when we need the freshest data)
177-
when (fetchingFreshRegistry || offline == OnlineBypassCache) do
177+
when (fetchingFreshRegistry || offline == OnlineBypassCache || offline == OnlineRefreshRegistry) do
178178
-- clone the registry and index repo, or update them
179179
logInfo "Refreshing the Registry Index..."
180180
parallelise
@@ -264,7 +264,7 @@ getMetadataImpl db onlineStatus name =
264264
-- Parallelised version of `getMetadataImpl`
265265
getMetadataForPackagesImpl :: Db -> OnlineStatus -> Array PackageName -> Spago (LogEnv ()) (Either String (Map PackageName Metadata))
266266
getMetadataForPackagesImpl db onlineStatus names = do
267-
(map Map.fromFoldable <<< sequence) <$> case onlineStatus == OnlineBypassCache of
267+
(map Map.fromFoldable <<< sequence) <$> case onlineStatus == OnlineBypassCache || onlineStatus == OnlineRefreshRegistry of
268268
true -> do
269269
logDebug "Bypassing cache, reading metadata from file"
270270
parTraverseSpago metadataFromFile names
@@ -367,31 +367,37 @@ isVersionCompatible installedVersion minVersion =
367367
[ a, b, _c ], [ x, y, _z ] | a /= 0 && a == x && b >= y -> true
368368
_, _ -> false
369369

370-
-- | Check if we have fetched the registry recently enough, so we don't hit the net all the time
371-
shouldFetchRegistryRepos :: a. Db -> Spago (LogEnv a) Boolean
372-
shouldFetchRegistryRepos db = do
370+
-- | Check if we have fetched the registry recently enough, so we don't hit the net all the time.
371+
-- | When `OnlineRefreshRegistry` is set, always fetch regardless of staleness.
372+
shouldFetchRegistryRepos :: a. OnlineStatus -> Db -> Spago (LogEnv a) Boolean
373+
shouldFetchRegistryRepos offline db = do
373374
now <- liftEffect $ Now.nowDateTime
374375
let registryKey = "registry"
375-
maybeLastRegistryFetch <- liftEffect $ Db.getLastPull db registryKey
376-
case maybeLastRegistryFetch of
377-
-- No record, so we have to fetch
378-
Nothing -> do
379-
logDebug "No record of last registry pull, will fetch"
380-
liftEffect $ Db.updateLastPull db registryKey now
381-
pure true
382-
-- We have a record, so we check if it's old enough
383-
Just lastRegistryFetch -> do
384-
let staleAfter = Minutes 15.0
385-
let (timeDiff :: Minutes) = DateTime.diff now lastRegistryFetch
386-
let isOldEnough = timeDiff > staleAfter
387-
-- We check if it's old, but also if we have it at all
388-
registryExists <- FS.exists Paths.registryPath
389-
if isOldEnough || not registryExists then do
390-
logDebug "Registry is old, refreshing"
376+
if offline == OnlineRefreshRegistry then do
377+
logDebug "Refresh flag set, will fetch registry"
378+
liftEffect $ Db.updateLastPull db registryKey now
379+
pure true
380+
else do
381+
maybeLastRegistryFetch <- liftEffect $ Db.getLastPull db registryKey
382+
case maybeLastRegistryFetch of
383+
-- No record, so we have to fetch
384+
Nothing -> do
385+
logDebug "No record of last registry pull, will fetch"
391386
liftEffect $ Db.updateLastPull db registryKey now
392387
pure true
393-
else do
394-
pure false
388+
-- We have a record, so we check if it's old enough
389+
Just lastRegistryFetch -> do
390+
let staleAfter = Minutes 15.0
391+
let (timeDiff :: Minutes) = DateTime.diff now lastRegistryFetch
392+
let isOldEnough = timeDiff > staleAfter
393+
-- We check if it's old, but also if we have it at all
394+
registryExists <- FS.exists Paths.registryPath
395+
if isOldEnough || not registryExists then do
396+
logDebug "Registry is old, refreshing"
397+
liftEffect $ Db.updateLastPull db registryKey now
398+
pure true
399+
else do
400+
pure false
395401

396402
--------------------------------------------------------------------------------
397403
-- | Registry operations

test-fixtures/1146-cli-help/build.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Invalid option `--bogus'
22

3-
Usage: index.dev.js build [--migrate] [--monochrome|--no-color] [--offline] [-q|--quiet] [-v|--verbose] [--backend-args ARGS] [--ensure-ranges] [--json-errors] [--output DIR] [--pedantic-packages] [--pure] [--purs-args ARGS] [-p|--package PACKAGE] ([--verbose-stats] | [--censor-stats]) [--strict]
3+
Usage: index.dev.js build [--migrate] [--monochrome|--no-color] [--offline] [--refresh] [-q|--quiet] [-v|--verbose] [--backend-args ARGS] [--ensure-ranges] [--json-errors] [--output DIR] [--pedantic-packages] [--pure] [--purs-args ARGS] [-p|--package PACKAGE] ([--verbose-stats] | [--censor-stats]) [--strict]
44
Compile the project
55

66
Available options:
@@ -9,6 +9,7 @@ Available options:
99
--offline Do not attempt to use the network. Warning: this will
1010
fail if you don't have the necessary dependencies
1111
already cached
12+
--refresh Force refresh of the Registry, bypassing the cache
1213
-q,--quiet Suppress all spago logging
1314
-v,--verbose Enable additional debug logging, e.g. printing `purs`
1415
commands

test-fixtures/1146-cli-help/registry-search.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Invalid option `--bogus'
22

3-
Usage: index.dev.js registry search [--migrate] [--monochrome|--no-color] [--offline] [-q|--quiet] [-v|--verbose] [--json] PACKAGE
3+
Usage: index.dev.js registry search [--migrate] [--monochrome|--no-color] [--offline] [--refresh] [-q|--quiet] [-v|--verbose] [--json] PACKAGE
44
Search for package names in the Registry
55

66
Available options:
@@ -9,6 +9,7 @@ Available options:
99
--offline Do not attempt to use the network. Warning: this will
1010
fail if you don't have the necessary dependencies
1111
already cached
12+
--refresh Force refresh of the Registry, bypassing the cache
1213
-q,--quiet Suppress all spago logging
1314
-v,--verbose Enable additional debug logging, e.g. printing `purs`
1415
commands

test-fixtures/init/subpackage/conflicting-flags.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Invalid option `--subpackage'
22

3-
Usage: index.dev.js init [--migrate] [--monochrome|--no-color] [--offline] [-q|--quiet] [-v|--verbose] ([--subpackage ARG] | [--name ARG]) [--package-set ARG] [--use-solver]
3+
Usage: index.dev.js init [--migrate] [--monochrome|--no-color] [--offline] [--refresh] [-q|--quiet] [-v|--verbose] ([--subpackage ARG] | [--name ARG]) [--package-set ARG] [--use-solver]
44
Initialise a new project
55

66
Available options:
@@ -9,6 +9,7 @@ Available options:
99
--offline Do not attempt to use the network. Warning: this will
1010
fail if you don't have the necessary dependencies
1111
already cached
12+
--refresh Force refresh of the Registry, bypassing the cache
1213
-q,--quiet Suppress all spago logging
1314
-v,--verbose Enable additional debug logging, e.g. printing `purs`
1415
commands

test/Spago/Install.purs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,19 @@ spec = Spec.around withTempDir do
138138
writeConfigWithEither testCwd
139139
spago [ "install", "--offline", "either" ] >>= shouldBeFailureErr (fixture "offline.txt")
140140

141+
Spec.it "refresh flag forces registry refresh and bypasses DB metadata cache" \{ spago, testCwd } -> do
142+
spago [ "init" ] >>= shouldBeSuccess
143+
-- The --refresh flag should force a registry refresh regardless of cache age
144+
result1 <- spago [ "install", "--refresh" ]
145+
shouldBeSuccess result1
146+
either _.stderr _.stderr result1 `shouldContain` "Refreshing the Registry Index..."
147+
-- Remove lockfile to force dependency resolution on next install
148+
FS.unlink (testCwd </> "spago.lock")
149+
-- With --refresh, should also bypass DB metadata cache and read from files
150+
result2 <- spago [ "install", "-v", "--refresh", "effect" ]
151+
shouldBeSuccess result2
152+
either _.stderr _.stderr result2 `shouldContain` "Bypassing cache, reading metadata from file"
153+
141154
Spec.it "skips cloning during resolution when git package has declared deps" \{ spago, testCwd, fixture } -> do
142155
FS.copyFile { src: fixture "git-declared-deps/with-declared-deps.yaml", dst: testCwd </> "spago.yaml" }
143156
FS.mkdirp (testCwd </> "src")

0 commit comments

Comments
 (0)