Skip to content

Commit b4c4dc5

Browse files
committed
Merge branch 'main' into connect-timeout
2 parents 9d56f3d + 721bcff commit b4c4dc5

File tree

12 files changed

+130
-49
lines changed

12 files changed

+130
-49
lines changed

.github/workflows/build.yml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: build
1+
name: Haskell
22

33
on:
44
push:
@@ -7,7 +7,7 @@ on:
77
tags:
88
- "v*"
99
paths:
10-
- ".github/workflows/**"
10+
- ".github/workflows/build.yml"
1111
- "src/**"
1212
- "test/**"
1313
- "test-postgres/**"
@@ -18,12 +18,14 @@ on:
1818

1919
jobs:
2020
build:
21+
name: "Build & Test"
2122
strategy:
2223
fail-fast: false
2324
matrix:
2425
resolver:
2526
- "stack-lts11"
2627
- "stack-lts18"
28+
- "stack-lts24"
2729
postgres-flag:
2830
- ""
2931
- "--flag network-wait:postgres"
@@ -36,6 +38,12 @@ jobs:
3638
steps:
3739
- uses: actions/checkout@v4
3840

41+
- name: Set up Docker Compose
42+
if: |
43+
contains(matrix.postgres-flag, 'network-wait:postgres') ||
44+
contains(matrix.redis-flag, 'network-wait:redis')
45+
uses: docker/setup-compose-action@v1
46+
3947
- uses: haskell/actions/setup@v2
4048
id: install-haskell
4149
with:
@@ -79,7 +87,7 @@ jobs:
7987
# only deploy the documentation for a build on `main` with all flags enabled
8088
if: |
8189
github.ref == 'refs/heads/main' &&
82-
matrix.resolver == 'stack-lts18' &&
90+
matrix.resolver == 'stack-lts24' &&
8391
contains(matrix.postgres-flag, 'network-wait:postgres') &&
8492
contains(matrix.redis-flag, 'network-wait:redis')
8593
uses: JamesIves/[email protected]
@@ -90,12 +98,12 @@ jobs:
9098
- name: Start Docker containers (PostgreSQL)
9199
if: ${{ contains(matrix.postgres-flag, 'network-wait:postgres') }}
92100
run: |
93-
docker-compose -p postgres -f docker-compose.postgresql.yaml up -d
101+
docker compose -p postgres -f docker-compose.postgresql.yaml up -d
94102
95103
- name: Start Docker containers (Redis)
96104
if: ${{ contains(matrix.redis-flag, 'network-wait:redis') }}
97105
run: |
98-
docker-compose -p redis -f docker-compose.redis.yaml up -d
106+
docker compose -p redis -f docker-compose.redis.yaml up -d
99107
100108
- name: Test
101109
run: |
@@ -107,9 +115,9 @@ jobs:
107115
- name: Stop Docker containers (PostgreSQL)
108116
if: ${{ contains(matrix.postgres-flag, 'network-wait:postgres') }}
109117
run: |
110-
docker-compose -p postgres -f docker-compose.postgresql.yaml down
118+
docker compose -p postgres -f docker-compose.postgresql.yaml down
111119
112120
- name: Stop Docker containers (Redis)
113121
if: ${{ contains(matrix.redis-flag, 'network-wait:redis') }}
114122
run: |
115-
docker-compose -p redis -f docker-compose.redis.yaml down
123+
docker compose -p redis -f docker-compose.redis.yaml down

.github/workflows/hackage.yml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,41 @@
1-
name: hackage
1+
name: Hackage
22

33
on:
44
push:
5-
tags:
6-
- 'v*'
5+
paths:
6+
- ".github/workflows/hackage.yml"
7+
release:
8+
types:
9+
- released
10+
- prereleased
711

812
jobs:
913
publish-to-hackage:
10-
name: 'Publish to Hackage'
14+
name: "Publish"
1115
runs-on: ubuntu-latest
1216

1317
steps:
14-
- uses: actions/checkout@v4
18+
- name: "Checkout repository"
19+
uses: actions/checkout@v4
1520

16-
- uses: haskell/actions/setup@v2
21+
- uses: haskell-actions/setup@v2
1722
id: install-haskell
1823
with:
1924
stack-no-global: true
2025
enable-stack: true
21-
stack-version: 'latest'
26+
stack-version: "latest"
2227

2328
- name: Configure stack
2429
run: |
2530
mkdir -p ${{ steps.install-haskell.outputs.stack-root }}
2631
echo "save-hackage-creds: false" >> ${{ steps.install-haskell.outputs.stack-root }}/config.yaml
2732
33+
- name: Check source distribution
34+
run: stack sdist .
35+
2836
- name: Publish `network-wait`
29-
if: startsWith(github.ref, 'refs/tags/v')
30-
run: stack upload .
37+
if: startsWith(github.ref, 'refs/tags/v') && github.event.action == 'released'
38+
run: stack upload . --candidate
3139
env:
3240
HACKAGE_USERNAME: ${{ secrets.HACKAGE_USER }}
3341
HACKAGE_PASSWORD: ${{ secrets.HACKAGE_PASSWORD }}

ChangeLog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog for network-wait
22

3+
## 0.3.0
4+
5+
- Functions in the `Network.Wait.PostgreSQL` module are now overloaded to accept different types of connection information. In addition to the previously supported `ConnectInfo` type, the function now also accept connection strings in the form of `ByteString` values.
6+
37
## 0.2.0
48

59
- Add `Network.Wait.Redis` module with functions to wait for Redis servers to become ready to accept connections. This module and its dependency on `hedis` are not enabled by default. The `network-wait:redis` flag must be enabled for this package's Redis support.

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# network-wait
22

33
![MIT](https://img.shields.io/github/license/mbg/network-wait)
4-
![CI](https://github.com/mbg/network-wait/workflows/build/badge.svg?branch=main)
4+
[![CI](https://github.com/mbg/network-wait/actions/workflows/build.yml/badge.svg)](https://github.com/mbg/network-wait/actions/workflows/build.yml)
55
[![Hackage](https://img.shields.io/hackage/v/network-wait)](https://hackage.haskell.org/package/network-wait)
66

77
A lightweight Haskell library for waiting on networked services to become available. This is useful if you are e.g. building a web application which relies on a database server to be available, but which may not be immediately available on application startup.
@@ -41,6 +41,23 @@ main = do
4141

4242
Internally, this uses `postgresql-simple` to connect to the specified server (`defaultConnectInfo` in the example above) and send a `SELECT 1;` query. If the query is answered correctly, we consider the server to be in a state ready to accept commands.
4343

44+
Alternatively, a connection string may be used instead of a `ConnectInfo` value:
45+
46+
```haskell
47+
import Data.ByteString (ByteString)
48+
import Control.Retry (retryPolicyDefault)
49+
import Database.PostgreSQL.Simple (defaultConnectInfo)
50+
import Network.Wait.PostgreSQL (waitPostgreSQL)
51+
52+
connStr :: ByteString
53+
connStr = "host=localhost port=5432"
54+
55+
main :: IO ()
56+
main = do
57+
waitPostgreSQL retryPolicyDefault connStr
58+
putStrLn "Yay, the PostgreSQL server is ready to accept commands!"
59+
```
60+
4461
The `Network.Wait.PostgreSQL` module is gated behind the `network-wait:postgres` flag so that the PostgreSQL-specific dependencies are only required when PostgresSQL support is required by users of this library.
4562

4663
## Example: Redis

network-wait.cabal

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
cabal-version: 1.12
22

3-
-- This file has been generated from package.yaml by hpack version 0.34.4.
3+
-- This file has been generated from package.yaml by hpack version 0.38.1.
44
--
55
-- see: https://github.com/sol/hpack
66

77
name: network-wait
8-
version: 0.2.0.0
8+
version: 0.3.0.0
99
synopsis: Lightweight library for waiting on networked services to become available.
1010
description: Please see the README on GitHub at <https://github.com/mbg/network-wait#readme> and
1111
Haddock documentation for all modules, including those that are gated behind
@@ -15,7 +15,7 @@ homepage: https://github.com/mbg/network-wait#readme
1515
bug-reports: https://github.com/mbg/network-wait/issues
1616
author: Michael B. Gale
1717
maintainer: [email protected]
18-
copyright: 2022 Michael B. Gale
18+
copyright: 2025 Michael B. Gale
1919
license: MIT
2020
license-file: LICENSE
2121
build-type: Simple
@@ -47,9 +47,11 @@ library
4747
ghc-options: -Wall
4848
build-depends:
4949
base >=4.7 && <5
50+
, bytestring
5051
, exceptions
5152
, network
5253
, retry
54+
default-language: Haskell2010
5355
if flag(postgres)
5456
build-depends:
5557
postgresql-simple
@@ -62,7 +64,6 @@ library
6264
if flag(redis)
6365
exposed-modules:
6466
Network.Wait.Redis
65-
default-language: Haskell2010
6667

6768
test-suite network-wait-test
6869
type: exitcode-stdio-1.0
@@ -74,20 +75,21 @@ test-suite network-wait-test
7475
ghc-options: -Wall
7576
build-depends:
7677
base >=4.7 && <5
78+
, bytestring
7779
, exceptions
7880
, network
7981
, network-simple
8082
, network-wait
8183
, retry
8284
, tasty
8385
, tasty-hunit
86+
default-language: Haskell2010
8487
if flag(postgres)
8588
build-depends:
8689
postgresql-simple
8790
if flag(redis)
8891
build-depends:
8992
hedis
90-
default-language: Haskell2010
9193

9294
test-suite network-wait-test-postgres
9395
type: exitcode-stdio-1.0
@@ -99,12 +101,14 @@ test-suite network-wait-test-postgres
99101
ghc-options: -Wall
100102
build-depends:
101103
base >=4.7 && <5
104+
, bytestring
102105
, exceptions
103106
, network
104107
, network-wait
105108
, retry
106109
, tasty
107110
, tasty-hunit
111+
default-language: Haskell2010
108112
if flag(postgres)
109113
build-depends:
110114
postgresql-simple
@@ -115,7 +119,6 @@ test-suite network-wait-test-postgres
115119
buildable: True
116120
else
117121
buildable: False
118-
default-language: Haskell2010
119122

120123
test-suite network-wait-test-redis
121124
type: exitcode-stdio-1.0
@@ -127,12 +130,14 @@ test-suite network-wait-test-redis
127130
ghc-options: -Wall
128131
build-depends:
129132
base >=4.7 && <5
133+
, bytestring
130134
, exceptions
131135
, network
132136
, network-wait
133137
, retry
134138
, tasty
135139
, tasty-hunit
140+
default-language: Haskell2010
136141
if flag(postgres)
137142
build-depends:
138143
postgresql-simple
@@ -143,4 +148,3 @@ test-suite network-wait-test-redis
143148
buildable: True
144149
else
145150
buildable: False
146-
default-language: Haskell2010

package.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
name: network-wait
2-
version: 0.2.0.0
2+
version: 0.3.0.0
33
github: "mbg/network-wait"
44
license: MIT
55
author: "Michael B. Gale"
66
maintainer: "[email protected]"
7-
copyright: "2022 Michael B. Gale"
7+
copyright: "2025 Michael B. Gale"
88

99
extra-source-files:
1010
- README.md
@@ -20,6 +20,7 @@ description: |
2020
2121
dependencies:
2222
- base >= 4.7 && < 5
23+
- bytestring
2324
- exceptions
2425
- network
2526
- retry

src/Network/Wait/PostgreSQL.hs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
-- connection can be established, the functions in this module also check
1313
-- whether the PostgreSQL server is ready to accept commands.
1414
module Network.Wait.PostgreSQL (
15+
PostgreSqlConnectInfo(..),
1516
waitPostgreSql,
1617
waitPostgreSqlVerbose,
1718
waitPostgreSqlVerboseFormat,
@@ -20,6 +21,8 @@ module Network.Wait.PostgreSQL (
2021

2122
-------------------------------------------------------------------------------
2223

24+
import Data.ByteString ( ByteString )
25+
2326
import Control.Monad
2427
import Control.Monad.Catch
2528
import Control.Monad.IO.Class
@@ -32,20 +35,32 @@ import Network.Wait
3235

3336
-------------------------------------------------------------------------------
3437

38+
-- | Used to abstract over different ways to describe a database connection.
39+
class PostgreSqlConnectInfo a where
40+
-- | `connectDb` @info@ attempts to establish a database connection using
41+
-- a configuration given by @info@.
42+
connectDb :: a -> IO Connection
43+
44+
instance PostgreSqlConnectInfo ConnectInfo where
45+
connectDb = connect
46+
47+
instance PostgreSqlConnectInfo ByteString where
48+
connectDb = connectPostgreSQL
49+
3550
-- | `waitPostgreSql` @retryPolicy connectInfo@ is a variant of
3651
-- `waitPostgresWith` which does not install any additional handlers.
3752
waitPostgreSql
38-
:: (MonadIO m, MonadMask m)
39-
=> RetryPolicyM m -> ConnectInfo -> m Connection
53+
:: (MonadIO m, MonadMask m, PostgreSqlConnectInfo info)
54+
=> RetryPolicyM m -> info -> m Connection
4055
waitPostgreSql = waitPostgreSqlWith []
4156

4257
-- | `waitPostgreSqlVerbose` @outputHandler retryPolicy connectInfo@ is a variant
4358
-- of `waitPostgreSqlVerboseFormat` which catches all exceptions derived from
4459
-- `SomeException` and formats retry attempt information using `defaultLogMsg`
4560
-- before passing the resulting `String` to @out@.
4661
waitPostgreSqlVerbose
47-
:: (MonadIO m, MonadMask m)
48-
=> (String -> m ()) -> RetryPolicyM m -> ConnectInfo -> m Connection
62+
:: (MonadIO m, MonadMask m, PostgreSqlConnectInfo info)
63+
=> (String -> m ()) -> RetryPolicyM m -> info -> m Connection
4964
waitPostgreSqlVerbose out =
5065
waitPostgreSqlVerboseFormat @SomeException $
5166
\b ex st -> out $ defaultLogMsg b ex st
@@ -55,10 +70,10 @@ waitPostgreSqlVerbose out =
5570
-- `logRetries` which passes status information for each retry attempt
5671
-- to @outputHandler@.
5772
waitPostgreSqlVerboseFormat
58-
:: forall e m . (MonadIO m, MonadMask m, Exception e)
73+
:: forall e m info. (MonadIO m, MonadMask m, PostgreSqlConnectInfo info, Exception e)
5974
=> (Bool -> e -> RetryStatus -> m ())
6075
-> RetryPolicyM m
61-
-> ConnectInfo
76+
-> info
6277
-> m Connection
6378
waitPostgreSqlVerboseFormat out = waitPostgreSqlWith [h]
6479
where h = logRetries (const $ pure True) out
@@ -74,13 +89,13 @@ waitPostgreSqlVerboseFormat out = waitPostgreSqlWith [h]
7489
-- @extraHandlers@ may also be used to report retry attempts to e.g. the
7590
-- standard output or a logger.
7691
waitPostgreSqlWith
77-
:: (MonadIO m, MonadMask m)
78-
=> [RetryStatus -> Handler m Bool] -> RetryPolicyM m -> ConnectInfo
92+
:: (MonadIO m, MonadMask m, PostgreSqlConnectInfo info)
93+
=> [RetryStatus -> Handler m Bool] -> RetryPolicyM m -> info
7994
-> m Connection
8095
waitPostgreSqlWith hs policy info =
8196
recoveringWith hs policy $ \_ ->
8297
liftIO $
83-
bracket (connect info) close $ \con -> do
98+
bracket (connectDb info) close $ \con -> do
8499
rs <- query_ @[Int] con "SELECT 1;"
85100
unless (rs == [[1]]) $ throwM $
86101
fatalError "Unexpected result for SELECT 1."

0 commit comments

Comments
 (0)