glue: Make better services.

[ bsd3, deprecated, library, network, program ] [ Propose Tags ]
Deprecated in favor of glue-common, glue-core, glue-ekg, glue-example

Implements common patterns used in building services that run smoothly and efficiently.

[Skip to Readme]


Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


  • No Candidates
Versions [RSS],,, 0.1.2, 0.1.3, 0.2.0
Dependencies async, base (>=4.6 && <4.9), ekg-core (>= && <1), glue, hashable, lifted-base, monad-control, monad-loops, text, time, transformers, transformers-base, unordered-containers [details]
License BSD-3-Clause
Author Sean Parsons
Category Network
Source repo head: git clone git://
Uploaded by seanparsons at 2015-08-24T22:54:49Z
Executables glue-example
Downloads 3780 total (14 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2015-08-24 [all 1 reports]

Readme for glue-0.2.0

[back to package description]

Building Better Services

Build Status

This package provides methods to deal with the common needs of services talking to other services, like timeouts and retries, treating these as cross-cutting concerns that aren't tied to a specific transport like HTTP.



In a social network there may be another service that returns user records, if this social network is really busy it would likely be more efficient to capture multiple calls and dispatch them as one multi-get call.

The batchingService function creates both single and multi-get calls (hence the "fmap snd" below), which accumulate requests over a user defined window in time and dispatch them once that window has passed.

data User = User Int String

makeUser :: Int -> User
makeUser userId = User userId ("User " ++ (show userId))

userService :: S.HashSet Int -> IO (M.HashMap Int User)
userService request = do
  threadDelay 500
  return $ M.fromList $ fmap (\r -> (r, makeUser r)) $ S.toList request

batchedUserService :: IO (S.HashSet Int -> IO (M.HashMap Int User))
batchedUserService = fmap snd $ batchingService defaultBatchingOptions userService


Often we want to retry service calls if they've failed because it might've been a transient error that subsequently succeeds.

failingService :: IORef Int -> Int -> IO Int
failingService ref request = do
  counter <- atomicModifyIORef' ref (\c -> (c + 1, c + 1))
  if counter `mod` 3 == 0 then fail "Bang!" else return (request * 2)

notSoFailingService :: IO (Int -> IO Int)
notSoFailingService = do
  ref <- liftIO $ newIORef 0
  return $ retryingService defaultRetryOptions $ failingService ref


serviceThatNeedsCaching :: Int -> IO Int
serviceThatNeedsCaching request = do
  putStrLn "Doing Something Expensive!"
  return (request * 2)

cachedService :: IO (Int -> IO Int)
cachedService = do
  cache <- newAtomicLRU $ Just 100
  return $ cacheWithLRU cache serviceThatNeedsCaching