diff --git a/.gitignore b/.gitignore
new file mode 100644
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+dist
+cabal-dev
+*.o
+*.hi
+*.chi
+*.chs.h
+.virtualenv
+.hsenv
+.cabal-sandbox/
+cabal.sandbox.config
+cabal.config
+*~
+*.swp
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,89 @@
+# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
+language: c
+sudo: false
+
+cache:
+  directories:
+    - $HOME/.cabsnap
+    - $HOME/.cabal/packages
+
+before_cache:
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
+
+matrix:
+  include:
+    - env: CABALVER=1.18 GHCVER=7.8.3
+      compiler: ": #GHC 7.8.3"
+      addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.3], sources: [hvr-ghc]}}
+    - env: CABALVER=1.18 GHCVER=7.8.4
+      compiler: ": #GHC 7.8.4"
+      addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
+    - env: CABALVER=1.22 GHCVER=7.10.1
+      compiler: ": #GHC 7.10.1"
+      addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.1], sources: [hvr-ghc]}}
+    - env: CABALVER=1.22 GHCVER=7.10.2
+      compiler: ": #GHC 7.10.2"
+      addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2], sources: [hvr-ghc]}}
+    - env: CABALVER=1.22 GHCVER=7.10.3
+      compiler: ": #GHC 7.10.3"
+      addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
+
+before_install:
+ - unset CC
+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
+ - bash eventstore-test-setup.sh
+
+install:
+ - cabal --version
+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
+ - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
+   then
+     zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
+          $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
+   fi
+ - travis_retry cabal update -v
+ - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
+ - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt
+ - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
+
+# check whether current requested install-plan matches cached package-db snapshot
+ - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;
+   then
+     echo "cabal build-cache HIT";
+     rm -rfv .ghc;
+     cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
+     cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
+   else
+     echo "cabal build-cache MISS";
+     rm -rf $HOME/.cabsnap;
+     mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
+     cabal install --only-dependencies --enable-tests --enable-benchmarks;
+   fi
+
+# snapshot package-db on cache miss
+ - if [ ! -d $HOME/.cabsnap ];
+   then
+      echo "snapshotting package-db to build-cache";
+      mkdir $HOME/.cabsnap;
+      cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
+      cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
+   fi
+
+# Here starts the actual work to be performed for the package under test;
+# any command which exits with a non-zero exit code causes the build to fail.
+script:
+ - if [ -f configure.ac ]; then autoreconf -i; fi
+ - cabal configure --enable-tests --enable-benchmarks -v2  # -v2 provides useful information for debugging
+ - cabal build   # this builds all libraries and executables (including tests/benchmarks)
+ - cabal test
+ - cabal check
+ - cabal sdist   # tests that a source-distribution can be generated
+
+# Check that the resulting source distribution can be built & installed.
+# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
+# `cabal install --force-reinstalls dist/*-*.tar.gz`
+ - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
+   (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
+
+# EOF
diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,8 @@
+0.9.1.0
+-------
+* Introduce convinient persistent subscription functions.
+* Add multi GHC version testing.
+
 0.9.0.0
 -------
 * Rewrite entirely the internals.
diff --git a/Database/EventStore.hs b/Database/EventStore.hs
--- a/Database/EventStore.hs
+++ b/Database/EventStore.hs
@@ -136,6 +136,10 @@
     , SystemConsumerStrategy(..)
     , NakAction(..)
     , S.PersistActionException(..)
+    , acknowledge
+    , acknowledgeEvents
+    , failed
+    , eventsFailed
     , notifyEventsProcessed
     , notifyEventsFailed
     , defaultPersistentSubscriptionSettings
@@ -384,6 +388,37 @@
 notifyEventsProcessed Subscription{..} evts = do
     run <- atomically $ readTMVar _subRun
     pushAckPersist _subProd run evts
+
+--------------------------------------------------------------------------------
+-- | Acknowledges that 'ResolvedEvent' has been successfully processed.
+acknowledge :: Subscription S.Persistent -> ResolvedEvent -> IO ()
+acknowledge sub e = notifyEventsProcessed sub [resolvedEventOriginalId e]
+
+--------------------------------------------------------------------------------
+-- | Acknowledges those 'ResolvedEvent's have been successfully processed.
+acknowledgeEvents :: Subscription S.Persistent -> [ResolvedEvent] -> IO ()
+acknowledgeEvents sub = notifyEventsProcessed sub . fmap resolvedEventOriginalId
+
+--------------------------------------------------------------------------------
+-- | Mark a message that has failed processing. The server will take action
+--   based upon the action parameter.
+failed :: Subscription S.Persistent
+       -> ResolvedEvent
+       -> NakAction
+       -> Maybe Text
+       -> IO ()
+failed sub e a r = notifyEventsFailed sub a r [resolvedEventOriginalId e]
+
+--------------------------------------------------------------------------------
+-- | Mark messages that have failed processing. The server will take action
+--   based upon the action parameter.
+eventsFailed :: Subscription S.Persistent
+             -> [ResolvedEvent]
+             -> NakAction
+             -> Maybe Text
+             -> IO ()
+eventsFailed sub evts a r =
+    notifyEventsFailed sub a r $ fmap resolvedEventOriginalId evts
 
 --------------------------------------------------------------------------------
 -- | Acknowledges those event ids have failed to be processed successfully.
diff --git a/eventstore-test-setup.sh b/eventstore-test-setup.sh
new file mode 100644
--- /dev/null
+++ b/eventstore-test-setup.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+wget http://download.geteventstore.com/binaries/EventStore-OSS-Ubuntu-v3.3.0.tar.gz
+tar -xf EventStore-OSS-Ubuntu-v3.3.0.tar.gz
+EventStore-OSS-Ubuntu-v3.3.0/run-node.sh --mem-db &
diff --git a/eventstore.cabal b/eventstore.cabal
--- a/eventstore.cabal
+++ b/eventstore.cabal
@@ -10,8 +10,10 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.9.0.0
+version:             0.9.1.0
 
+tested-with: GHC >= 7.8.3 && < 7.11
+
 -- A short (one-line) description of the package.
 synopsis: EventStore TCP Client
 
@@ -44,6 +46,9 @@
 -- README.
 extra-source-files:  README.md
                      CHANGELOG.markdown
+                     .gitignore
+                     .travis.yml
+                     eventstore-test-setup.sh
 
 -- Constraint on the version of Cabal needed to build this package.
 cabal-version:       >=1.10
