WaitSet: scalable mechanism for listening for changes to one or more accounts
--------------------------------------------------------------------------------
Non-admin versions in the 'zimbraMail' Namespace:
-------------------------------------------------
Admin versions in the 'zimbraAdmin' Namespace:
-------------------------------------------------
note that the admin versions of the APIs are identical in any way,
except that they can be used to wait on non-owner accounts and can be
used to wait on "all accounts".
*************************************
INTEREST_TYPES: comma-separated list. Currently:
f: folders
m: messages
c: contacts
a: appointments
t: tasks
d: documents
all: all types (equiv to "f,m,c,a,t,d")
*************************************
CreateWaitSet/AdminCreateWaitSet: must be called once to initialize
the WaitSet and to set its "default interest types"
- Non-Admin requests may only specify their own account ID.
- Non-Admin accounts are restricted to a max of 5 (default,
overridable via LocalConfig) WaitSets. Creating more than the max
will cause the least-recently-used WaitSet to be destroyed
- If "allAccounts" is set, then all mailboxes on the system will be
listened to, including any mailboxes which are created on the system
while the WaitSet is in existence. Additionally:
-- , and tags are IGNORED
-- The requesting authtoken must be an admin token
- AllAccounts WaitSets are *semi-persistent*, that is, even if the
server restarts, it is OK to call passing in your
previous sequence number. The server will attempt to resynchronize
the waitset using the sequence number you provide (the server's
ability to do this is limited by the RedoLogs that are available)
================
<[Admin]CreateWaitSetRequest defTypes="DEFAULT INTEREST_TYPES" [allAccounts=1]>
[
[]+
]
[Admin]CreateWaitSetRequest>
<[Admin]CreateWaitSetResponse waitSet="setId" defTypes="types" seq="0">
[ ]*
[Admin]CreateWaitSetResponse>
ERROR_CODEs:
// RUNTIME errors:
MAILBOX_DELETED: the mailbox has been deleted, it is no longer in the waitset
// ADD errors:
ALREADY_IN_SET_DURING_ADD: the account was not added, it was already there
ERROR_LOADING_MAILBOX: exception while trying to fetch the mailbox, not added
MAINTENANCE_MODE: mailbox currently in Maintenance Mode. Try to add it again later.
NO_SUCH_ACCOUNT: unknown account, not added
WRONG_HOST_FOR_ACCOUNT: that account's mailbox is on another host. Add it there.
// REMOVE/UPDATE errors
NOT_IN_SET_DURING_REMOVE
NOT_IN_SET_DURING_UPDATE
***IMPORTANT: Note that the seq number is **NOT** guaranteed to be an
integer. Clients MUST treat this value as an opaque string.***
************************************
WaitSetRequest/AdminWaitSetRequest: optionally modifies the wait set
and checks for any notifications. If block=1 and there are no
notifications, then this API will BLOCK until there is data.
Client should always set 'seq' to be the highest known value it has
received from the server. The server will use this information to
retransmit lost data.
If the client sends a last known sync token then the notification is
calculated by comparing the accounts current token with the client's
last known.
If the client does not send a last known sync token, then notification
is based on change since last Wait (or change since if this
is the first time Wait has been called with the account)
The client may specify a custom timeout-length for their request if
they know something about the particular underlying network. The
server may or may not honor this request (depending on server
configured max/min values). The server will allow a wider range of
requested timeouts from admin auth tokens. See LocalConfig values:
zimbra_waitset_default_request_timeout,
zimbra_waitset_min_request_timeout,
zimbra_waitset_max_request_timeout,
zimbra_admin_waitset_default_request_timeout,
zimbra_admin_waitset_min_request_timeout, and
zimbra_admin_waitset_max_request_timeout
================
<[Admin]WaitSetRequest waitSet="setId" defTypes="DEFAULT INTEREST TYPES"
seq="highestSeqKnown" [block="1"] [timeout="timeout"]>
[
[]+
]
[
[]+
]
[
[]+
]
[Admin]WaitSetRequest>
<[Admin]WaitSetResponse waitSet="setId" [seq="seqNo" OR canceled="1"]>
[ ]*
[ ]*
[Admin]WaitSetResponse>
If the specified wait set does not exist, the server will throw an
admin.NO_SUCH_WAITSET exception.
NOTE: an empty response to a blocking request *is* possible: it would
happen if the server timed-out the waiting. The server does this
occasionally just so that requests don't get "stuck". The client
should re-submit the original request if this happens.
If a second WaitMultiple request arrives at the server while one is
already waiting, the first request will be immediately completed and
will return with the "canceled" flag set.
ERROR_CODEs:
// RUNTIME errors:
MAILBOX_DELETED: the mailbox has been deleted, it is no longer in the waitset
// ADD errors:
ALREADY_IN_SET_DURING_ADD: the account was not added, it was already there
ERROR_LOADING_MAILBOX: exception while trying to fetch the mailbox, not added
MAINTENANCE_MODE: mailbox currently in Maintenance Mode. Try to add it again later.
NO_SUCH_ACCOUNT: unknown account, not added
WRONG_HOST_FOR_ACCOUNT: that account's mailbox is on another host. Add it there.
// REMOVE/UPDATE errors
NOT_IN_SET_DURING_REMOVE
NOT_IN_SET_DURING_UPDATE
*************************************
DestroyWaitSet/AdminDestroyWaitSet: Use this to close out the wait
set. Note that the server will automatically time out a wait set if
there is no reference to it for (default of) 20 minutes.
*************************************
<[Admin]DestroyWaitSetRequest waitSet="setId"/>
<[Admin]DestroyWaitSetResponse waitSet="setId"/>
**********************************************************************
There are three basic use cases for WaitSets:
**********************************************************************
1) wait on a single account:
2) Wait on many accounts (admin-only -- Remember to use the
zimbraAdmin namespace):
3) Wait on ALL accounts (admin-only):
...
// SERVER RESTARTS!
...
// server will re-sync using RedoLogs
**********************************************************************
A Detailed Example:
**********************************************************************
*************************************
QueryWaitSet
This API dumps the internal state of all active waitsets. It is
intended for debugging use only and should not be used for
production uses. This API is not guaranteed to be stable between
releases in any way and might be removed without warning.
*************************************
SomeAccountsWaitSet:
----------------------
[]?
[
[
]?
]*
AllAccountsWaitSet:
-------------------
[
[]* // only during WS creation before first WaitSetRequest
]?
[]?