| Portability | non-portable (uses GHC extensions) | 
|---|---|
| Maintainer | lemmih@gmail.com | 
| Safe Haskell | None | 
Data.Acid.Remote
Contents
Description
This module provides the ability perform update and query calls
from a remote process.
On the server-side you:
-  open your AcidStatenormally
-  then use acidServerto share the state
On the client-side you:
-  use openRemoteStateto connect to the remote state
-  use the returned AcidStatelike any otherAcidStatehandle
openRemoteState and acidServer communicate over an unencrypted
socket. If you need an encrypted connection, see acid-state-tls.
On Unix®-like systems you can useUnixSocket to create a socket file for
local communication between the client and server. Access can be
controlled by setting the permissions of the parent directory
containing the socket file.
It is also possible to perform some simple authentication using
sharedSecretCheck and sharedSecretPerform. Keep in mind that
secrets will be sent in plain-text if you do not use
acid-state-tls. If you are using a UnixSocket additional
authentication may not be required, so you can use
skipAuthenticationCheck and skipAuthenticationPerform.
Working with a remote AcidState is nearly identical to working with
a local AcidState with a few important differences.
The connection to the remote AcidState can be lost. The client will
automatically attempt to reconnect every second. Because query
events do not affect the state, an aborted query will be retried
automatically after the server is reconnected.
If the connection was lost during an update event, the event will
not be retried. Instead RemoteConnectionError will be raised. This
is because it is impossible for the client to know if the aborted
update completed on the server-side or not.
When using a local AcidState, an update event in one thread does not
block query events taking place in other threads. With a remote
connection, all queries and requests are channeled over a single
connection. As a result, updates and queries are performed in the
order they are executed and do block each other. In the rare case
where this is an issue, you could create one remote connection per
thread.
When working with local state, a query or update which returns the whole state is not usually a problem due to memory sharing. The update/query event basically just needs to return a pointer to the data already in memory. But, when working remotely, the entire result will be serialized and sent to the remote client. Hence, it is good practice to create queries and updates that will only return the required data.
This module is designed to be extenible. You can easily add your own
authentication methods by creating a suitable pair of functions and
passing them to acidServer and openRemoteState.
It is also possible to create alternative communication layers using
CommChannel, process, and processRemoteState.
- acidServer :: SafeCopy st => (CommChannel -> IO Bool) -> PortID -> AcidState st -> IO ()
- acidServer' :: SafeCopy st => (CommChannel -> IO Bool) -> Socket -> AcidState st -> IO ()
- openRemoteState :: IsAcidic st => (CommChannel -> IO ()) -> HostName -> PortID -> IO (AcidState st)
- skipAuthenticationCheck :: CommChannel -> IO Bool
- skipAuthenticationPerform :: CommChannel -> IO ()
- sharedSecretCheck :: Set ByteString -> CommChannel -> IO Bool
- sharedSecretPerform :: ByteString -> CommChannel -> IO ()
- data AcidRemoteException
- data  CommChannel  = CommChannel {- ccPut :: ByteString -> IO ()
- ccGetSome :: Int -> IO ByteString
- ccClose :: IO ()
 
- process :: SafeCopy st => CommChannel -> AcidState st -> IO ()
- processRemoteState :: IsAcidic st => IO CommChannel -> IO (AcidState st)
Server/Client
Arguments
| :: SafeCopy st | |
| => (CommChannel -> IO Bool) | check authentication, see  | 
| -> PortID | Port to listen on | 
| -> AcidState st | state to serve | 
| -> IO () | 
Accept connections on port and handle requests using the given AcidState.
     This call doesn't return.
On Unix®-like systems you can useUnixSocket to communicate
     using a socket file. To control access, you can set the permissions of
     the parent directory which contains the socket file.
see also: openRemoteState and sharedSecretCheck.
Arguments
| :: SafeCopy st | |
| => (CommChannel -> IO Bool) | check authentication, see  | 
| -> Socket | binded socket to accept connections from | 
| -> AcidState st | state to serve | 
| -> IO () | 
Works the same way as acidServer, but uses pre-binded socket listenSocket.
Can be useful when fine-tuning of socket binding parameters is needed (for example, listening on a particular network interface, IPv4/IPv6 options).
Arguments
| :: IsAcidic st | |
| => (CommChannel -> IO ()) | authentication function, see  | 
| -> HostName | remote host to connect to (ignored when  | 
| -> PortID | remote port to connect to | 
| -> IO (AcidState st) | 
Connect to an acid-state server which is sharing an AcidState. 
Authentication
skipAuthenticationCheck :: CommChannel -> IO BoolSource
skip server-side authentication checking entirely.
skipAuthenticationPerform :: CommChannel -> IO ()Source
skip client-side authentication entirely.
Arguments
| :: Set ByteString | set of shared secrets | 
| -> CommChannel -> IO Bool | 
check that the client knows a shared secret.
The function takes a Set of shared secrets. If a client knows any
of them, it is considered to be trusted.
The shared secret is any ByteString of your choice.
If you give each client a different shared secret then you can revoke access individually.
see also: sharedSecretPerform
Arguments
| :: ByteString | shared secret | 
| -> CommChannel -> IO () | 
attempt to authenticate with the server using a shared secret.
Exception type
Low-Level functions needed to implement additional communication channels
data CommChannel Source
CommChannel is a record containing the IO functions we need for communication between the server and client.
We abstract this out of the core processing function so that we can easily add support for SSL/TLS and Unit testing.
Constructors
| CommChannel | |
| Fields 
 | |
Arguments
| :: SafeCopy st | |
| => CommChannel | a connected, authenticated communication channel | 
| -> AcidState st | state to share | 
| -> IO () | 
Server inner-loop
This function is generally only needed if you are adding a new communication channel.
Arguments
| :: IsAcidic st | |
| => IO CommChannel | (re-)connect function | 
| -> IO (AcidState st) | 
Client inner-loop
This function is generally only needed if you are adding a new communication channel.