runStore :: MonadStore a -> IO (Either String a, [Logger])
runStore code = do
  bracket (open sockPath) close run
  where
    open path = do
      soc <- socket AF_UNIX Stream 0
      connect soc (SockAddrUnix path)
      return soc
    greet = do
      sockPut $ putInt workerMagic1
      soc <- ask
      vermagic <- liftIO $ recv soc 16
      let (magic2, daemonProtoVersion) = flip runGet (LBS.fromStrict vermagic) $ (,) <$> getInt <*> getInt
      unless (magic2 == workerMagic2) $ error "Worker magic 2 mismatch"

      sockPut $ putInt protoVersion -- clientVersion
      sockPut $ putInt (0 :: Int)   -- affinity
      sockPut $ putInt (0 :: Int)   -- obsolete reserveSpace

      processOutput

    run sock =
      flip runReaderT sock $ flip runStateT [] $ runExceptT (greet >> code)
runStore :: MonadStore a -> IO (Either String a, [Logger])
runStore code = do
  bracket (open sockPath) close run
  where
    open path = do
      soc <- socket AF_UNIX Stream 0
      connect soc (SockAddrUnix path)
      return soc
    greet = do
      sockPut $ putInt workerMagic1
      soc <- ask
      vermagic <- liftIO $ recv soc 16
      let (magic2, daemonProtoVersion) = flip runGet (LBS.fromStrict vermagic) $ (,) <$> getInt <*> getInt
      unless (magic2 == workerMagic2) $ error "Worker magic 2 mismatch"

      sockPut $ putInt protoVersion -- clientVersion
      sockPut $ putInt (0 :: Int)   -- affinity
      sockPut $ putInt (0 :: Int)   -- obsolete reserveSpace

      processOutput

    run sock =
      flip runReaderT sock $ flip runStateT [] $ runExceptT (greet >> code)
runStore code = do
  bracket (open sockPath) close run
  where
    open path = do
      soc <- socket AF_UNIX Stream 0
      connect soc (SockAddrUnix path)
      return soc
    greet = do
      sockPut $ putInt workerMagic1
      soc <- ask
      vermagic <- liftIO $ recv soc 16
      let (magic2, daemonProtoVersion) = flip runGet (LBS.fromStrict vermagic) $ (,) <$> getInt <*> getInt
      unless (magic2 == workerMagic2) $ error "Worker magic 2 mismatch"

      sockPut $ putInt protoVersion -- clientVersion
      sockPut $ putInt (0 :: Int)   -- affinity
      sockPut $ putInt (0 :: Int)   -- obsolete reserveSpace

      processOutput

    run sock =
      flip runReaderT sock $ flip runStateT [] $ runExceptT (greet >> code)