-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
{-| | ||
Module: Squeal.PostgreSQL.Session.Notify | ||
Description: database notification | ||
Copyright: (c) Eitan Chatav, 2019 | ||
Maintainer: [email protected] | ||
Stability: experimental | ||
Support for receiving asynchronous notifications | ||
via PostgreSQL's Listen/Notify mechanism. | ||
See https://www.postgresql.org/docs/current/sql-notify.html | ||
for more information. | ||
-} | ||
|
||
{-# LANGUAGE | ||
DataKinds | ||
, PolyKinds | ||
, RankNTypes | ||
, TypeOperators | ||
#-} | ||
|
||
module Squeal.PostgreSQL.Session.Notify | ||
( getNotification | ||
, getNotificationWithConfig | ||
) where | ||
|
||
import Data.Function ((&)) | ||
import UnliftIO | ||
|
||
import qualified Database.PostgreSQL.LibPQ as LibPQ | ||
import qualified Database.PostgreSQL.LibPQ.Notify as LibPQ | ||
import qualified Generics.SOP as SOP | ||
|
||
import Squeal.PostgreSQL.Session.Exception | ||
import Squeal.PostgreSQL.Session | ||
|
||
{-| | ||
Returns a single notification. If no notifications are | ||
available, 'getNotificationWithConfig' blocks until one arrives. | ||
Unlike 'getNotification', 'getNotificationWithConfig' takes in an | ||
additional 'Config' parameter which provides custom 'interrupt' and | ||
various event hooks for operational insight. | ||
Using a custom 'interrupt' is necessary if one would like to call | ||
'getNotificationWithConfig' on one thread and @NOTIFY@ on another | ||
thread using the same connection. | ||
To support this behavior one must cause 'interrupt' to return after the | ||
call to @NOTIFY@ checks it's result from the server. | ||
See the test file of this package for an example of how to use a custom | ||
'interrupt'. | ||
Note that PostgreSQL does not | ||
deliver notifications while a connection is inside a transaction. | ||
-} | ||
getNotificationWithConfig | ||
:: MonadUnliftIO io | ||
=> LibPQ.Config | ||
-> PQ db db io LibPQ.Notify | ||
getNotificationWithConfig config = PQ $ \ (SOP.K conn) -> do | ||
noteOrErr <- liftIO $ LibPQ.getNotificationWithConfig config (&) conn | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
echatav
Author
Contributor
|
||
case noteOrErr of | ||
Left err -> throwSqueal (NotificationException err) | ||
Right note -> return (SOP.K note) | ||
{-| | ||
Returns a single notification. If no notifications are | ||
available, 'getNotification' blocks until one arrives. | ||
If 'getNotification' is called and afterwards on a different thread | ||
@NOTIFY@ is called using the same connection, 'getNotification' can | ||
block even if a notification is sent. | ||
To support this behavior one must use 'getNotificationWithConfig' instead. | ||
Note that PostgreSQL does not | ||
deliver notifications while a connection is inside a transaction. | ||
-} | ||
getNotification | ||
:: MonadUnliftIO io | ||
=> PQ db db io LibPQ.Notify | ||
getNotification = getNotificationWithConfig LibPQ.defaultConfig |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ resolver: lts-15.6 | |
packages: | ||
- free-categories-0.2.0.0 | ||
- with-utf8-1.0.0.0 | ||
- postgresql-libpq-notify-0.1.0.0 |
So this is not ideal because
getNotificationWithConfig
will block and I guess hold onto the connection. If the connection was wrapped in aMVar
getNotificationWithConfig
will only hold the connection as it setup to wait on the notification but give up the lock as it is waiting.I think this will work it just is not the best use of connections.