summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlyokha <>2019-12-02 10:58:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2019-12-02 10:58:00 (GMT)
commit032450d11eac9cda825a3910db13e201f4e07eb5 (patch)
treebc3262813d52fc0e3b6e97df9a367de6f48d40e6
parent27b0a2dfbb41aefa0d5a48f2b24af12f2f533fb8 (diff)
version 0.1.0.1HEAD0.1.0.1master
-rw-r--r--Changelog.md5
-rw-r--r--NgxExport/Tools/Aggregate.hs58
-rw-r--r--ngx-export-tools-extra.cabal2
3 files changed, 34 insertions, 31 deletions
diff --git a/Changelog.md b/Changelog.md
index ca402b9..8b654e7 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,8 @@
+### 0.1.0.1
+
+- Docs improved (using *strict variable handlers* from the latest
+ *nginx-haskell-module* in the example).
+
### 0.1.0.0
- Initial version.
diff --git a/NgxExport/Tools/Aggregate.hs b/NgxExport/Tools/Aggregate.hs
index 881e7be..da62857 100644
--- a/NgxExport/Tools/Aggregate.hs
+++ b/NgxExport/Tools/Aggregate.hs
@@ -87,7 +87,6 @@ type Aggregate a = IORef (CTime, Map Int32 (CTime, Maybe a))
-- import Data.Aeson
-- import Data.Maybe
-- import Data.IORef
--- import Control.Monad
-- import System.IO.Unsafe
-- import GHC.Generics
--
@@ -113,14 +112,13 @@ type Aggregate a = IORef (CTime, Map Int32 (CTime, Maybe a))
-- return \"\"
-- 'NgxExport.ngxExportIOYY' \'updateStats
--
--- reportStats :: ByteString -> Bool -> IO C8L.ByteString
--- __/reportStats/__ = 'deferredService' $ \conf -> do
--- let port = 'readFromByteString' \@Int conf
--- when (isJust port) $ do
--- s <- readIORef stats
--- 'reportAggregate' (fromJust port) (Just s) \"__/stats/__\"
+-- reportStats :: Int -> Bool -> IO C8L.ByteString
+-- __/reportStats/__ = 'deferredService' $ \\port -> do
+-- s <- readIORef stats
+-- 'reportAggregate' port (Just s) \"__/stats/__\"
-- return \"\"
--- 'ngxExportSimpleService' \'reportStats $ PersistentService $ Just $ Sec 5
+-- 'ngxExportSimpleServiceTyped' \'reportStats \'\'Int $
+-- 'PersistentService' $ Just $ Sec 5
--
-- 'ngxExportAggregateService' \"__/stats/__\" \'\'Stats
-- @
@@ -153,17 +151,12 @@ type Aggregate a = IORef (CTime, Map Int32 (CTime, Maybe a))
-- default_type application\/octet-stream;
-- sendfile on;
--
--- log_format combined1 \'$remote_addr - $remote_user [$time_local] \'
--- \'\"$request\" $status $body_bytes_sent \'
--- \'\"$http_referer\" \"$http_user_agent\"\'
--- \'$hs_updateStats\';
---
-- haskell load \/var\/lib\/nginx\/test_tools_extra.so;
--
-- haskell_run_service __/simpleService_aggregate_stats/__ $hs_stats
-- \'__/AggregateServerConf/__ { __/asPort/__ = 8100, __/asPurgeInterval/__ = Min 5 }\';
--
--- haskell_service_var_in_shm stats 64k \/tmp $hs_stats;
+-- haskell_service_var_in_shm stats 32k \/tmp $hs_stats;
--
-- haskell_run_service __/simpleService_reportStats/__ $hs_reportStats 8100;
--
@@ -171,9 +164,9 @@ type Aggregate a = IORef (CTime, Map Int32 (CTime, Maybe a))
-- listen 8010;
-- server_name main;
-- error_log \/tmp\/nginx-test-haskell-error.log;
--- access_log \/tmp\/nginx-test-haskell-access.log combined1;
+-- access_log \/tmp\/nginx-test-haskell-access.log;
--
--- haskell_run __/updateStats/__ $hs_updateStats $bytes_sent;
+-- haskell_run __/updateStats/__ !$hs_updateStats $bytes_sent;
--
-- location \/ {
-- echo Ok;
@@ -203,15 +196,16 @@ type Aggregate a = IORef (CTime, Map Int32 (CTime, Maybe a))
-- shared with Nginx directive /haskell_service_var_in_shm/), otherwise it won't
-- even start because the internal HTTP servers on each worker process won't be
-- able to bind to the same TCP port. Inside the upper /server/ clause, handler
--- /updateStats/ runs on every client request. However, as soon as Nginx
--- variable handlers are /lazy/, evaluation of /$hs_updateStats/ must be forced
--- somewhere: the log phase is a good choice for this (Nginx internal variable
--- /$bytes_sent/ has already been evaluated at this point). That's why
--- /$hs_updateStats/ (which is always empty, but has valuable side effects) is
--- put inside of the /log_format combined1/ without any risk of affecting the
--- actual formatting.
---
--- Data collected by the aggregate server can be obtained in a request to the
+-- /updateStats/ runs on every client request. This handler always returns an
+-- empty string in variable /$hs_updateStats/ because it is only needed for the
+-- side effect of updating the /stats/. However, as soon as Nginx variable
+-- handlers are /lazy/, evaluation of /$hs_updateStats/ must be forced somehow.
+-- To achieve this, we used the /strict annotation/ (the /bang/ symbol) in
+-- directive /haskell_run/ that enforces strict evaluation in a late request
+-- processing phase, when the value of variable /$bytes_sent/ has been already
+-- calculated.
+--
+-- Data collected by the aggregate service can be obtained in a request to the
-- virtual server listening on TCP port /8020/. It simply proxies requests to
-- the internal aggregate server with URL /\/get\/__stats__/ where __/stats/__
-- corresponds to the /name/ of the aggregate service.
@@ -298,7 +292,7 @@ type Aggregate a = IORef (CTime, Map Int32 (CTime, Maybe a))
-- @
--
-- The value of /asPort/ corresponds to the TCP port of the internal aggregate
--- server. The /asPurgeInterval/ is the /purge/ interval. An aggregate server
+-- server. The /asPurgeInterval/ is the /purge/ interval. An aggregate service
-- should sometimes purge data from worker processes which did not report for a
-- long time. For example, it makes no sense to keep data from workers that
-- have already been terminated. The inactive PIDs get checked every
@@ -385,6 +379,9 @@ throwUserError = ioError . userError
-- exactly referred from 'reportAggregate' and client requests to the service
-- because the URL of the internal HTTP server contains this.
--
+-- The aggregate type must have instances of 'FromJSON' and 'ToJSON' as its
+-- objects will be transferred via HTTP in JSON format.
+--
-- The service is implemented via 'ngxExportSimpleServiceTyped' with
-- 'AggregateServerConf' as the name of its custom type. This is an
-- 'ignitionService' with an HTTP server based on the [Snap
@@ -424,13 +421,14 @@ ngxExportAggregateService f a = do
,ngxExportSimpleServiceTyped
fName ''AggregateServerConf SingleShotService
]
--- | Reports data to an aggregate server.
+-- | Reports data to an aggregate service.
--
--- If reported data is 'Nothing' then the aggregated data won't alter, but the
--- timestamp associated with the PID of this worker process will be updated.
+-- If reported data is 'Nothing' then data collected on the aggregate service
+-- won't alter except that the timestamp associated with the PID of the sending
+-- worker process will be updated.
reportAggregate :: ToJSON a => Int -- ^ Port of the aggregate server
-> Maybe a -- ^ Reported data
- -> ByteString -- ^ Name of the aggregate server
+ -> ByteString -- ^ Name of the aggregate service
-> IO ()
reportAggregate p v u =
handle (const $ return () :: SomeException -> IO ()) $ do
diff --git a/ngx-export-tools-extra.cabal b/ngx-export-tools-extra.cabal
index 3654c57..6fc2ab7 100644
--- a/ngx-export-tools-extra.cabal
+++ b/ngx-export-tools-extra.cabal
@@ -1,5 +1,5 @@
name: ngx-export-tools-extra
-version: 0.1.0.0
+version: 0.1.0.1
synopsis: More extra tools for Nginx haskell module
description: More extra tools for
<http://github.com/lyokha/nginx-haskell-module Nginx haskell module>.