diff options
author | Marko Kreen | 2007-08-22 12:37:42 +0000 |
---|---|---|
committer | Marko Kreen | 2007-08-22 12:37:42 +0000 |
commit | fd016b8589476e9ef32e7d9d2d5426328d4d7f0b (patch) | |
tree | 8cfcaa55c41aee95b70ec32ba92a163ec63d9e93 | |
parent | bfe0862cd69f6157ed5e9205dd1cd3da048c3a44 (diff) |
Add INSTALL.txt, convert rest to asciidoc
Dimitri Fontaine & Marko Kreen
-rw-r--r-- | INSTALL | 104 | ||||
-rw-r--r-- | README | 50 | ||||
-rw-r--r-- | doc/Makefile | 21 | ||||
-rw-r--r-- | doc/TODO.txt | 89 | ||||
-rw-r--r-- | doc/londiste.ref.txt | 223 | ||||
-rw-r--r-- | doc/pgq-admin.txt | 64 | ||||
-rw-r--r-- | doc/pgq-sql.txt | 43 |
7 files changed, 330 insertions, 264 deletions
diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..521b2149 --- /dev/null +++ b/INSTALL @@ -0,0 +1,104 @@ += SkyTools - tools for PostgreSQL = + +This is a package of tools in use in Skype for replication and +failover. Also it includes a generic queuing mechanism PgQ and +utility library for Python scripts. + +== Dependencies == + +Skytools modules use some other code to run, you need to install the +following dependencies on the system where you want to build and run +skytool applications. + +=== Build dependencies === + + libevent-dev postgresql-8.2 postgresql-server-dev-8.2 autoconf + devscripts yada + +=== Runtime dependencies === + + python + python-psycopg or python2.4-psycopg + skytools-modules-8.2 or the version matching your PostgreSQL installation + postgresql-plpython-8.2 (or your version of PostgreSQL) + +== Building a debian package == + +The main Makefile provides a target for building a +.deb+ package +suitable for installation. You need to install some packages to be +able to build the debian package, the list is given in previous +section. + +Then the build: + + $ make deb82 + +You can build skytools for older PostgreSQL systems by choosing one of ++deb81+ or +deb80+ targets. + +The build should give you two debian package files to install, such as ++skytools_2.1.5_i386.deb+ and ++skytools-modules-8.2_2.1.5_i386.deb+. See the Installation section +for notes about where to install those packages. + +== Building for other systems == + +The build and install from sources step are the following: + + $ autoconf + $ ./configure [--prefix] [--with-python] [--with-pgconfig] + $ make + $ sudo make install + +The following configure options are available: + +--prefix:: + path prefix where to install skytools files (default: UNKNOWN) + +--with-python:: + name of the Python executable (default: python) + +--with-pgconfig:: + path to pg_config (default: pg_config) + + +== Documentation == + +Skytools documentation consist of text files, some of them in the +asciidoc format, from which you can produce man and html outputs: + + $ cd doc + $ make man + $ make html + +You need asciidoc and xmlto packages for this to work. + +== Installation == + +=== Skytools === + +You have to install skytools on the machines where you want to run it, +obviously. The installation of the skytools provides PgQ, Londiste and +walmgr. + +=== Londiste === + +In the londiste case, as the replication process will run on only one +machine (either provider, subscriber or a tier box), things are not +that straight anymore. + +But simple nonetheless: install PgQ on the machine where you want to +run it, provider being the straightforward choice. Then install +londiste only on the box from where you want to launch the replication +process, a good default begin the subscriber box this time. + +You can then install londiste on provider from the subscriber box with +the +londiste.py+ command line tool. + +== Usage == + +Please refer to the documentation. + + + + @@ -1,47 +1,55 @@ - -SkyTools - tools for PostgreSQL -=============================== += SkyTools - tools for PostgreSQL = This is a package of tools in use in Skype for replication and failover. Also it includes a generic queuing mechanism PgQ and utility library for Python scripts. +== Overview == + It contains following tools: -PgQ ---- +=== PgQ === -This is the queue machanism we use. Consists of PL/pgsql, PL/python -and C code in database, with Python framework on top of it. It is -based on snapshot based event handling ideas from Slony-I, -written for general usage. +This is the queue machanism we use. Consists of PL/pgsql, and C code +in database, with Python framework on top of it. It is based on +snapshot based event handling ideas from Slony-I, written for general +usage. Features: - * There can be several queues in database. - * There can be several producers than can insert into any queue. - * There can be several consumers on one queue and all consumers - see all events. +- There can be several queues in database. +- There can be several producers than can insert into any queue. +- There can be several consumers on one queue and all consumers see + all events. +Documentation: -Londiste --------- +- PgQ admin tool (pgqadm) usage: doc/pgq-admin.txt +- PgQ SQL API overview: doc/pgq-sql.txt +- PgQ SQL reference: http://skytools.projects.postgresql.org/pgq/ + +=== Londiste === Replication tool written in Python, using PgQ as event transport. Features: + - Tables can be added one-by-one into set. -- Initial COPY for one table does not block event replay - for other tables. +- Initial COPY for one table does not block event replay for other + tables. - Can compare tables on both sides. +Documentation: -walmgr ------- +- Londiste script usage: doc/londiste.cmdline.txt + (also available as `man 1 londiste`) +- Londiste configuration: doc/londiste.config.txt + (also available as `man 5 londiste`) +- Londiste reference: doc/londiste.ref.txt + +=== walmgr === This script will setup WAL archiving, does initial backup and runtime WAL archive and restore. - - diff --git a/doc/Makefile b/doc/Makefile index f908b907..7a997819 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -9,10 +9,13 @@ EPYDOC = epydoc-py25 EPYARGS = --no-private --url="http://pgfoundry.org/projects/skytools/" \ --name="Skytools" --html --no-private +HTMLS = londiste.cmdline.html londiste.config.html README.html INSTALL.html \ + londiste.ref.html TODO.html pgq-sql.html pgq-admin.html + all: man man: londiste.1 londiste.5 -html: londiste.cmdline.html londiste.config.html +html: $(HTMLS) install: man mkdir -p $(mandir)/man1 @@ -20,7 +23,7 @@ install: man install -m 644 londiste.1 $(mandir)/man1 install -m 644 londiste.5 $(mandir)/man1 -upload: +old.wiki.upload: devupload.sh overview.txt $(wiki) devupload.sh TODO.txt $(wiki)/ToDo #devupload.sh londiste.txt $(wiki)/LondisteUsage @@ -65,10 +68,22 @@ londiste.5: londiste.config.xml asciidoc -d manpage -b docbook $< %.html: %.txt - asciidoc $< + asciidoc -a toc $< manupload: man html rsync -avz londiste.[15] *.html *.txt pgf:web/skytools/htdocs/man/ +README.html: ../README + cat $< \ + | sed -e 's,doc/\([!-~]*\)[.]txt,link:\1.html[],g' \ + -e 's,http:[!-~]*,&[],g' \ + | asciidoc -o $@ - + +INSTALL.html: ../INSTALL + asciidoc -o $@ $< + +web: $(HTMLS) + rsync -avz $(HTMLS) pgf:web/skytools/htdocs/new/ + diff --git a/doc/TODO.txt b/doc/TODO.txt index c203ce89..8b3eaae0 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -1,23 +1,23 @@ -[[TableOfContents]] += Skytools ToDo list = -= Next minor release - 2.1.5 = +== Next minor release - 2.1.5 == -== Done == +=== Done === * londiste fkeys: look also at dependers not only dependencies. * pgq.consumer: make queue seeking in case of failover more strict. * scriptmgr: dont die on user error. * pgq: there was still fallout from reorg - 2 missing indexes. * Due to historical reasons SerialConsumer (and thus Londiste) - accessed completed tick table directly, not via functions. - Make it use functions again. + accessed completed tick table directly, not via functions. + Make it use functions again. * Support psycopg2, preferring it to psycopg1. * Improved bulk_loader, using temp tables exclusively. * skytools.config: API change to allow usage without config file. * quote_ident(), quote_fqident() * Rewrite pgq.insert_event() in C, thus PgQ core is not - dependant on PL/Python anymore. + dependant on PL/Python anymore. * set client_encoding on subscriber same as on provider * Write PgQ triggers (pgq.logtriga(), pgq.logutriga(), pgq.sqltriga()) in C. * londiste: remove tbl should work also if table is already dropped [dimitri] @@ -25,94 +25,97 @@ * pgq: pgqadm also vacuums londiste and pgq_ext tables, if they exist * londiste: provider add/remove --all [hans] * londiste: remove denytrigger from source, thus no plpython anymore... - it was unused anyway. + it was unused anyway. * replace logtriga() with pgq.logtriga() for londiste trigger * backend modules need to be ported to 8.3 * londiste: good fkey support: store them in subscriber db and apply when both tables are in sync. [erik] -== To Do == +=== To Do === + * pgqadm docs * add <seq>, remove <seq> [marko] * pgq/londiste/pgq_ext: schema upgrade scripts [marko] -= Next major release - 2.2 = +== Next major release - 2.2 == * cascaded replication, switchover, failover [marko] * skytools: config from database * drop support for psycopg1 * drop support for 8.1? -= High-prority = +== High-prority == -== Larger things == +=== Larger things === * docs: londiste, pgq/python, pgq/sql, skytools, walmgr -== Smaller things == +=== Smaller things === * pgq: RemoteConsumer/SerialConsumer/pgq_ext sanity, too much duplication [marko] * londiste: create tables on subscriber * pgqadm: Utility commands: - * reg-copy que cons1 cons2 - * reg-move que cons1 cons2 - * queue-rename - * show-batch-events - * del-event + - reg-copy que cons1 cons2 + - reg-move que cons1 cons2 + - queue-rename + - show-batch-events + - del-event * londiste: londiste status cmd - * check what modules are installed - * check if replay is running (lag?) - * check if copy is running (lag?) - * count of tables done, count of unsynced - * table in the middle of copy + - check what modules are installed + - check if replay is running (lag?) + - check if copy is running (lag?) + - count of tables done, count of unsynced + - table in the middle of copy -= Low-priority = +== Low-priority == -== Larger things == +=== Larger things === * londiste: denytriggers on subscriber * londiste: Quote SQL identifiers, keep combined name, rule will be "Split schema as first dot" * skylog: publish sample logdb schema, with some tools * londiste: allow table redirection on subscriber side * londiste: trigger handling - * `copy` drops triggers uncontitionally (except maybe disabled triggers in 8.3) - * there are "show-triggers" and "restore-triggers" commands that help - admin to review them, take manual action if needed and restore the trigger + - `copy` drops triggers uncontitionally (except maybe disabled triggers in 8.3) + - there are "show-triggers" and "restore-triggers" commands that help + admin to review them, take manual action if needed and restore the trigger -== Smaller things == +=== Smaller things === * londiste: make sure unprivileged provider connection works for ordinery replication, - but not for admin commands. Need to remove SECURITY DEFINER from londiste - admin functions (both provider and subscriber, because londiste needs admin - rights on subscriber anyway). + but not for admin commands. Need to remove SECURITY DEFINER from londiste + admin functions (both provider and subscriber, because londiste needs admin + rights on subscriber anyway). * pgqadm: separate priod for retry queue processing * skytools: switch for silence for cron scripts * pgq: drop_fkeys.sql for live envs * logdb: hostname * DBScript: failure to write pidfile should be logged (crontscripts) * ideas from SlonyI: - * force timestamps to ISO - * when buffering queries, check their size - * store event_id with tick, thus making possible to guess the size of - upcoming batches. + - force timestamps to ISO + - when buffering queries, check their size + - store event_id with tick, thus making possible to guess the size of + upcoming batches. * pgqadm: show count of events to be processed [--count switch]. - it should be relatively cheap with optimized query if consumers are not lagging. - * exact method - `SELECT count(*) FROM pgq.event_X WHERE NOT txid_in_snapshot(ev_txid, last_tick_snapshot) AND ev_txid > xmin;` - * can be optimized: `(ev_txid > xmax OR ev_txid IN get_snapshot_active())` - * several consumer can be done in one go if spread out to separate columns - * inexact method: take ev_id near xmax and compare with value from sequence - * broken by retry events, rollbacked transactions and use of force_tick() + it should be relatively cheap with optimized query if consumers are not lagging. + - exact method - `SELECT count(*) FROM pgq.event_X WHERE NOT txid_in_snapshot(ev_txid, last_tick_snapshot) AND ev_txid > xmin;` + Can be optimized: `(ev_txid > xmax OR ev_txid IN get_snapshot_active())`. + Several consumer can be done in one go if spread out to separate columns. + - inexact method: take ev_id near xmax and compare with value from sequence + * broken by retry events, rollbacked transactions and use of force_tick() * automatic "repair" - after reaching sync point, the "replay" must be killed, then fixes can be applied -= Just ideas = +== Just ideas == * skytools: config-less operation? * skytools: partial sql parser for log processing * londiste: EXECUTE SCRIPT * londiste: somehow automatic sync of table structure/functions/...? -= walmgr = +== walmgr == (walmgr needs thorough review of pending issues) * copy master config to slave * slave needs to decide which config to use + + diff --git a/doc/londiste.ref.txt b/doc/londiste.ref.txt index fe28478a..0b7d0954 100644 --- a/doc/londiste.ref.txt +++ b/doc/londiste.ref.txt @@ -1,9 +1,9 @@ -[[TableOfContents]] += Londiste Reference = -= Notes = +== Notes == -== PgQ daemon == +=== PgQ daemon === Londiste runs as a consumer on PgQ. Thus `pgqadm.py ticker` must be running on provider database. It is preferable to run it in same machine, because @@ -11,29 +11,29 @@ it needs low latency, but that is not a requirement. For monitoring you can use `pgqadm.py status` command. -== Table Names == +=== Table Names === Londiste internally uses table names always fully schema-qualified. If table name without schema is given on command line, it just puts "public." in front of it, without looking at search_path. -== PgQ events == +=== PgQ events === -''' Table change event ''' +==== Table change event ==== Those events will be inserted by triggers on tables. * ev_type = 'I' / 'U' / 'D' * ev_data = partial SQL statement - the part between `[]` is removed: - * `[ INSERT INTO table ] (column1, column2) values (value1, value2)` - * `[ UPDATE table SET ] column2=value2 WHERE pkeycolumn1 = value1` - * `[ DELETE FROM table WHERE ] pkeycolumn1 = value1` + - `[ INSERT INTO table ] (column1, column2) values (value1, value2)` + - `[ UPDATE table SET ] column2=value2 WHERE pkeycolumn1 = value1` + - `[ DELETE FROM table WHERE ] pkeycolumn1 = value1` * ev_extra1 = table name with schema Such partial SQL format is used for 2 reasons - to conserve space and to make possible to redirect events to another table. -''' Registration change event ''' +==== Registration change event ==== Those events will be inserted by `provider add` and `provider remove` commands. Then full registered tables list will be sent to the queue @@ -55,125 +55,104 @@ pairs between `{}`. Their meaning: * ignored: how many of them was ignores - table not registered on subscriber or not yet in sync. * duration: how long the batch processing took. -= Commands for managing provider database = +Example: -== provider install == + {count: 110, duration: 0.88} -{{{ -londiste.py <config.ini> provider install -}}} +== Commands for managing provider database == + +=== provider install === + + londiste.py <config.ini> provider install Installs code into provider and subscriber database and creates queue. Equivalent to doing following by hand: -{{{ -CREATE LANGUAGE plpgsql; -CREATE LANGUAGE plpython; -\i .../contrib/txid.sql -\i .../contrib/logtriga.sql -\i .../contrib/pgq.sql -\i .../contrib/londiste.sql -select pgq.create_queue(queue name); -}}} + CREATE LANGUAGE plpgsql; + CREATE LANGUAGE plpython; + \i .../contrib/txid.sql + \i .../contrib/logtriga.sql + \i .../contrib/pgq.sql + \i .../contrib/londiste.sql + select pgq.create_queue(queue name); Notes: - * If the PostgreSQL modules are not installed on same machine - the Python scripts are, the commands need to be done by hand. - * The schema/tables are installed under user Londiste is configured to run. If you prefer to run Londiste under non-admin user, they should also be installed by hand. -== provider add == +=== provider add === -{{{ -londiste.py <config.ini> provider add <table name> ... -}}} + londiste.py <config.ini> provider add <table name> ... Registers table on provider database and adds trigger to the table that will send events to the queue. -== provider remove == +=== provider remove === -{{{ -londiste.py <config.ini> provider remove <table name> ... -}}} + londiste.py <config.ini> provider remove <table name> ... Unregisters table on provider side and removes triggers on table. The event about table removal is also sent to the queue, so all subscriber unregister table from their end also. -== provider tables == +=== provider tables === -{{{ -londiste.py <config.ini> provider tables -}}} + londiste.py <config.ini> provider tables Shows registered tables on provider side. -== provider seqs == +=== provider seqs === -{{{ -londiste.py <config.ini> provider seqs -}}} + londiste.py <config.ini> provider seqs Shows registered sequences on provider side. -= Commands for managing subscriber database = +== Commands for managing subscriber database == -== subscriber install == +=== subscriber install === -{{{ -londiste.py <config.ini> subscriber install -}}} + londiste.py <config.ini> subscriber install Installs code into subscriber database. Equivalent to doing following by hand: -{{{ -CREATE LANGUAGE plpgsql; -\i .../contrib/londiste.sql -}}} + CREATE LANGUAGE plpgsql; + \i .../contrib/londiste.sql This will be done under Londiste user, if the tables should be owned by someone else, it needs to be done by hand. -== subscriber add == +=== subscriber add === -{{{ -londiste.py <config.ini> subscriber add <table name> ... [--excect-sync | --skip-truncate | --force] -}}} + londiste.py <config.ini> subscriber add <table name> ... [--excect-sync | --skip-truncate | --force] Registers table on subscriber side. Switches - * --excect-sync: Table is tagged as in-sync so initial COPY is skipped. - * --skip-truncate: When doing initial COPY, don't remove old data. - * --force: Ignore table structure differences. + --excect-sync:: Table is tagged as in-sync so initial COPY is skipped. + --skip-truncate:: When doing initial COPY, don't remove old data. + --force:: Ignore table structure differences. -== subscriber remove == +=== subscriber remove === -{{{ -londiste.py <config.ini> subscriber remove <table name> ... -}}} + londiste.py <config.ini> subscriber remove <table name> ... Unregisters the table from subscriber. No events will be applied to the table anymore. Actual table will not be touched. -== subscriber resync == +=== subscriber resync === -{{{ -londiste.py <config.ini> subscriber resync <table name> ... -}}} + londiste.py <config.ini> subscriber resync <table name> ... Tags tables are "not synced." Later replay process will notice this and launch `copy` process to sync the table again. -= Replication commands = +== Replication commands == -== replay == +=== replay === The actual replication process. Should be run as daemon with `-d` switch, because it needs to be always running. @@ -181,23 +160,24 @@ because it needs to be always running. It main task is to get a batches from PgQ and apply them in one transaction. Basic logic: + * Get batch from PgQ queue on provider. See if it is already applied to - subsciber, skip the batch in that case. + subsciber, skip the batch in that case. * Management actions, can do transactions on subscriber: - * Load table state from subscriber, to be up-to-date on registrations - and `copy` processes running in parallel. - * If a `copy` process wants to give table over to main process, - wait until `copy` process catches-up. - * If there is a table that is not synced and no `copy` process - is already running, launch new `copy` process. - * If there are sequences registered on subscriber, look latest state - of them on provider and apply it to subscriber. + - Load table state from subscriber, to be up-to-date on registrations + and `copy` processes running in parallel. + - If a `copy` process wants to give table over to main process, + wait until `copy` process catches-up. + - If there is a table that is not synced and no `copy` process + is already running, launch new `copy` process. + - If there are sequences registered on subscriber, look latest state + of them on provider and apply it to subscriber. * Event replay, all in one transaction on subscriber: - * Apply events from the batch, only for tables that are registered - on subscriber and are in sync. - * Store tick_id on subscriber. + - Apply events from the batch, only for tables that are registered + on subscriber and are in sync. + - Store tick_id on subscriber. -== copy (internal) == +=== copy (internal) === Internal command for initial SYNC. Launched by `replay` if it notices that some tables are not in sync. The reason to do table copying in @@ -205,27 +185,30 @@ separate process is to avoid locking down main replay process for long time. Basic logic: + * Register on the same queue in parallel with different name. - * One transaction on : - * Drop constraints and indexes. - * Truncate table. - * COPY data in. - * Restore constraints and indexes. - * Tag the table as `catching-up`. + * One transaction on subscriber: + - Drop constraints and indexes. + - Truncate table. + - COPY data in. + - Restore constraints and indexes. + - Tag the table as `catching-up`. * When catching-up, the `copy` process acts as regular - `replay` process but just for one table. + `replay` process but just for one table. * When it reaches queue end, when no more batches are immidiately - available, it hands the table over to main `replay` process. + available, it hands the table over to main `replay` process. State changes between `replay` and `copy`: -|| State || Owner || What is done || -|| `NULL` || replay || Changes state to `in-copy`, launches `londiste.py copy` process, continues with it's work || -|| `in-copy` || copy || drops indexes, truncates, copies data in, restores indexes, changes state to `catching-up` || -|| `catching-up` || copy || replay events for that table only until no more batches (means current moment), change state to `wanna-sync:<tick_id>` and wait for state to change || -|| `wanna-sync:<tick_id>` || replay || catch up to given tick_id, change state to 'do-sync:<tick_id>' and wait for state to change || -|| `do-sync:<tick_id>` || copy || catch up to given tick_id, both `replay` and `copy` must now be at same position. change state to `ok` and exit || -|| `ok` || replay || synced table, events can be applied || + State | Owner | What is done + ---------------------+--------+-------------------- + NULL | replay | Changes state to "in-copy", launches londiste.py copy process, continues with it's work + in-copy | copy | drops indexes, truncates, copies data in, restores indexes, changes state to "catching-up" + catching-up | copy | replay events for that table only until no more batches (means current moment), + | | change state to "wanna-sync:<tick_id>" and wait for state to change + wanna-sync:<tick_id> | replay | catch up to given tick_id, change state to "do-sync:<tick_id>" and wait for state to change + do-sync:<tick_id> | copy | catch up to given tick_id, both replay and copy must now be at same position. change state to "ok" and exit + ok | replay | synced table, events can be applied Such state changes must guarantee that any process can die at any time and by just restarting it can continue where it left. @@ -234,9 +217,9 @@ continue where it left. "subscriber resync" sets table state to `NULL`. -= Utility commands = +== Utility commands == -== repair == +=== repair === it tries to achieve a state where tables should be in sync and then compares them and writes out SQL statements that would fix differences. @@ -252,31 +235,29 @@ then comparing line-by-line. As this is CPU and memory-hungry operation, good practice is to run the `repair` command on third machine, to avoid consuming resources on neither provider nor subscriber. -== compare == +=== compare === it syncs tables like repair, but just runs SELECT count(*) on both sides, to get a little bit cheaper but also less precise way of checking if tables are in sync. -= Config file = - -{{{ -[londiste] -job_name = test_to_subcriber - -# source database, where the queue resides -provider_db = dbname=provider port=6000 host=127.0.0.1 - -# destination database -subscriber_db = dbname=subscriber port=6000 host=127.0.0.1 - -# the queue where to listen on -pgq_queue_name = londiste.replika - -# where to log -logfile = ~/log/%(job_name)s.log - -# pidfile is used for avoiding duplicate processes -pidfile = ~/pid/%(job_name)s.pid +== Config file == + + [londiste] + job_name = test_to_subcriber + + # source database, where the queue resides + provider_db = dbname=provider port=6000 host=127.0.0.1 + + # destination database + subscriber_db = dbname=subscriber port=6000 host=127.0.0.1 + + # the queue where to listen on + pgq_queue_name = londiste.replika + + # where to log + logfile = ~/log/%(job_name)s.log + + # pidfile is used for avoiding duplicate processes + pidfile = ~/pid/%(job_name)s.pid -}}} diff --git a/doc/pgq-admin.txt b/doc/pgq-admin.txt index 1ea9fddb..4873dfe7 100644 --- a/doc/pgq-admin.txt +++ b/doc/pgq-admin.txt @@ -2,41 +2,37 @@ == Config == -{{{ -[pgqadm] -job_name = pgqadm_somedb - -db = dbname=somedb - -# how often to run maintenance [minutes] -maint_delay_min = 5 - -# how often to check for activity [secs] -loop_delay = 0.1 - -logfile = ~/log/%(job_name)s.log -pidfile = ~/pid/%(job_name)s.pid - -}}} + [pgqadm] + job_name = pgqadm_somedb + + db = dbname=somedb + + # how often to run maintenance [minutes] + maint_delay_min = 5 + + # how often to check for activity [secs] + loop_delay = 0.1 + + logfile = ~/log/%(job_name)s.log + pidfile = ~/pid/%(job_name)s.pid == Command line usage == -{{{ -$ pgqadm.py --help -usage: pgqadm.py [options] INI CMD [subcmd args] - -commands: - ticker start ticking & maintenance process - status show overview of queue healt - -options: - -h, --help show this help message and exit - -q, --quiet make program silent - -v, --verbose make program verbose - -d, --daemon go background + $ pgqadm.py --help + usage: pgqadm.py [options] INI CMD [subcmd args] + + commands: + ticker start ticking & maintenance process + status show overview of queue healt + + options: + -h, --help show this help message and exit + -q, --quiet make program silent + -v, --verbose make program verbose + -d, --daemon go background + + control running process: + -r, --reload reload config (send SIGHUP) + -s, --stop stop program safely (send SIGINT) + -k, --kill kill program immidiately (send SIGTERM) - control running process: - -r, --reload reload config (send SIGHUP) - -s, --stop stop program safely (send SIGINT) - -k, --kill kill program immidiately (send SIGTERM) -}}} diff --git a/doc/pgq-sql.txt b/doc/pgq-sql.txt index 4e662f9d..090cb244 100644 --- a/doc/pgq-sql.txt +++ b/doc/pgq-sql.txt @@ -2,9 +2,7 @@ == Queue creation == -{{{ pgq.create_queue(queue_name text) -}}} Initialize event queue. @@ -12,10 +10,8 @@ Returns 0 if event queue already exists, 1 otherwise. == Producer == -{{{ pgq.insert_event(queue_name text, ev_type, ev_data) pgq.insert_event(queue_name text, ev_type, ev_data, extra1, extra2, extra3, extra4) -}}} Generate new event. This should be called inside main tx - thus rollbacked with it if needed. @@ -23,24 +19,18 @@ rollbacked with it if needed. == Consumer == -{{{ pgq.register_consumer(queue_name text, consumer_id text) -}}} Attaches this consumer to particular event queue. Returns 0 if the consumer was already attached, 1 otherwise. -{{{ pgq.unregister_consumer(queue_name text, consumer_id text) -}}} Unregister and drop resources allocated to customer. -{{{ pgq.next_batch(queue_name text, consumer_id text) -}}} Allocates next batch of events to consumer. @@ -48,9 +38,7 @@ Returns batch id (int8), to be used in processing functions. If no batches are available, returns NULL. That means that the ticker has not cut them yet. This is the appropriate moment for consumer to sleep. -{{{ pgq.get_batch_events(batch_id int8) -}}} `pgq.get_batch_events()` returns a set of events in this batch. @@ -60,22 +48,16 @@ with pgq.finish_batch(). Event fields: (ev_id int8, ev_time timestamptz, ev_txid int8, ev_retry int4, ev_type text, ev_data text, ev_extra1, ev_extra2, ev_extra3, ev_extra4) -{{{ pgq.event_failed(batch_id int8, event_id int8, reason text) -}}} Tag event as 'failed' - it will be stored, but not further processing is done. -{{{ pgq.event_retry(batch_id int8, event_id int8, retry_seconds int4) -}}} Tag event for 'retry' - after x seconds the event will be re-inserted into main queue. -{{{ pgq.finish_batch(batch_id int8) -}}} Tag batch as finished. Until this is not done, the consumer will get same batch again. @@ -88,46 +70,36 @@ of that batch. All operations must be done before. Events tagged as failed just stay on their queue. Following functions can be used to manage them. -{{{ pgq.failed_event_list(queue_name, consumer) pgq.failed_event_list(queue_name, consumer, cnt, offset) pgq.failed_event_count(queue_name, consumer) -}}} Get info about the queue. Event fields are same as for pgq.get_batch_events() -{{{ pgq.failed_event_delete(queue_name, consumer, event_id) pgq.failed_event_retry(queue_name, consumer, event_id) -}}} Remove an event from queue, or retry it. == Info operations == -{{{ pgq.get_queue_info() -}}} Get list of queues. Result: () -{{{ pgq.get_consumer_info() pgq.get_consumer_info(queue_name) pgq.get_consumer_info(queue_name, consumer) -}}} Get list of active consumers. Result: () -{{{ pgq.get_batch_info(batch_id) -}}} Get info about batch. @@ -141,50 +113,37 @@ Consumer '''must''' be able to process same event several times. First, create event queue: -{{{ select pgq.create_queue('LogEvent'); -}}} Then, producer side can do whenever it wishes: -{{{ select pgq.insert_event('LogEvent', 'data', 'DataFor123'); -}}} First step for consumer is to register: -{{{ select pgq.register_consumer('LogEvent', 'TestConsumer'); -}}} Then it can enter into consuming loop: -{{{ begin; select pgq.next_batch('LogEvent', 'TestConsumer'); [into batch_id] commit; -}}} That will reserve a batch of events for this consumer. To see the events in batch: -{{{ select * from pgq.get_batch_events(batch_id); -}}} That will give all events in batch. The processing does not need to be happen all in one transaction, framework can split the work how it wants. If a events failed or needs to be tried again, framework can call: -{{{ select pgq.event_retry(batch_id, event_id, 60); select pgq.event_failed(batch_id, event_id, 'Record deleted'); -}}} When all done, notify core about it: -{{{ select pgq.finish_batch(batch_id) -}}} + |