@need 3200

@node arch Triggers
@chapter arch Triggers

@geindex notify



In some circumstances, it is very useful to trigger actions upon the
detection of changes to an archive.  For example, you might want to
send an email notification whenever new revisions are checked in.


The command @code{notify} provides this capability:

@example
@group
        % larch notify NOTIFICATION-DIR
@end group
@group
@end group
@end example

That command reads configuration files found in @code{NOTIFICATION-DIR}.
Those configuration files explain what parts of which repositories to
monitor, and what actions to take upon changes.  When changes are
detected, @code{notify} invokes actions.


This chapter explains @code{notify} in general.  It documents the format of
a @code{NOTIFICATION-DIR} and the configuration files.  It explains what
@code{notify} does.  Later in the manual is documentation explaining how to
use @code{notify} to achieve certain specific effects.

@need 3200

@section The Four notify Configuration Files

|=rules.archives|
|=rules.categories|
|=rules.branches|
|=rules.versions|


@code{notify} is controlled by four configuration files, found at the root
of a @code{NOTIFICATION-DIR}.  These are:

@example
@group
        =rules.archives
                Specifies actions to take whenever new categories
                are added to specific archives.
@end group
@group
@end group
@end example
@example
@group
        =rules.categories
                Specifies actions to take whenever new branches
                are added to specific categories.
@end group
@group
@end group
@end example
@example
@group
        =rules.branches
                Specifies actions to take whenever new versions
                are added to specific branches.
@end group
@group
@end group
@end example
@example
@group
        =rules.versions
                Specifies actions to take whenever new revisions
                are added to specific versions.
@end group
@group
@end group
@end example

Within these files, blank lines are permitted and comments begin with
'#' and continue to the end of line. 


The file @code{=rules.versions} contains lines with the format:

@example
@group
        VERSION         ACTION
@end group
@group
@end group
@end example

@noindent
where @code{VERSION} is a fully-qualified version name, and action a string
(with no whitespace) of the form:

@example
@group
        COMMAND:THUNK
@end group
@group
@end group
@end example

Whenever new revisions are detected in @code{VERSION}, @code{notify} invokes:

@example
@group
        larch COMMAND THUNK RVN ...
@end group
@group
@end group
@end example

@noindent
where @code{COMMAND} and @code{THUNK} are from the configuration file, and the
trailing @code{RVN} arguments are a list of fully qualified revision names
of newly detected revisions.


The file @code{=rules.branches} is similar.  It contains lines of the form:

@example
@group
        BRANCH COMMAND:THUNK VERSION-ACTION
@end group
@group
@end group
@end example

Whenever new versions are created in @code{BRANCH}, @code{notify} takes two
actions.  First, it invokes:

@example
@group
        larch COMMAND THUNK VSN ...
@end group
@group
@end group
@end example

Second, it adds new rules to @code{=rules.versions} of the form:

@example
@group
        VSN     VERSION-ACTION
@end group
@group
@end group
@end example

The files @code{=rules.categories} and @code{=rules.archives} are similar.  The
former contains lines of the form:

@example
@group
        CATEGORY COMMAND:THUNK BRANCH-ACTION VERSION-ACTION
@end group
@group
@end group
@end example

@noindent
and the latter lines of the form:

@example
@group
        ARCHIVE COMMAND:THUNK CATEGORY-ACT BRANCH-ACT VERSION-ACT
@end group
@group
@end group
@end example

In addition to the configuration files, @code{notify} maintains its private
state in @code{NOTIFY-DIR}.  In particular, it keeps track of what
notifications have already been sent, in order to try to avoid sending
redundant notifications.




@need 3200

@section Triggers for Everything in a Repository 

Configuring triggers for every category, branch, and version in an
archive is quite simple: you only need to write the @code{=rules.archives}
file -- other configuration files will be automatically genrated from
that.


The initial @code{=rules.archives} file should contain lines of the form:

@example
@group
        ARCHIVE COMMAND:THUNK CATEGORY-ACT BRANCH-ACT VERSION-ACT
@end group
@group
@end group
@end example

@noindent
for ach set of actions you want to trigger.  After creating the config
file, run @code{notify} in that directory.  The first run will detect all
categories in the repository, invoke @code{COMMAND} for those, and create a
@code{rules.categories} file with lines:

@example
@group
        CATEGORY CATEGORY-ACT BRANCH-ACT VERSION-ACT
@end group
@group
@end group
@end example

Then @code{notify} will read that config file, detect all the branches in
the repository, invoke @code{CATEGORY-ACT}, and create @code{=rules.branches}.


Finally, @code{=rules.versions} will be automatically created in a similar
way.


Whenever a new category, branch, or version is added to an archive,
the rules files will be automatically updated to reflect the addition
(when @code{notify} is run, of course).




@need 3200

@section Robustness Issues with Triggers

Unfortunately, some fundamental physical properties of the universe
make it impossible for @code{notify} to guarantee that actions will be
invoked only once for each new category, branch, version, or revision.
A (presumably rare) well timed interrupt or system failure can cause
@code{notify} to invoke actions more than once for a given change to the
archive.  


Consequently, actions should be designed to be robust against that
eventuality.


@code{notify} is designed to be safe in the face of concurrent invocations:
if two processes invoke @code{notify} at the same time, everything should
work wonderfully with no resultant redundant actions or @code{NOTIFY-DIR}
corruptions.




@need 3200

@section Scheduling Triggers with cron

One strategy for using @code{notify} is to run it from a @code{cron} job.




@need 3200

@section Scheduling Triggers Directly

@geindex my-category-action

@geindex my-branch-action

@geindex my-version-action

@geindex my-revision-action



These commands (and only these commands) modify arch repositories in
ways that are significant to @code{notify}:

@example
@group
        make-category
        make-branch
        make-version
        import
        commit
@end group
@group
@end group
@end example

Corresponding to those commands, are four others:

@example
@group
        % larch my-category-action COMMAND ARGUMENTS...
@end group
@group
@end group
@end example
@example
@group
        % larch my-branch-action COMMAND ARGUMENTS...
@end group
@group
@end group
@end example
@example
@group
        % larch my-version-action COMMAND ARGUMENTS...
@end group
@group
@end group
@end example
@example
@group
        % larch my-revision-action COMMAND ARGUMENTS...
@end group
@group
@end group
@end example

@noindent
which in those invocations, set an action to be taken upon successful
completion of an archive transaction, and in these invocations:

@example
@group
        % larch my-category-action
@end group
@group
@end group
@end example
@example
@group
        % larch my-branch-action
@end group
@group
@end group
@end example
@example
@group
        % larch my-version-action
@end group
@group
@end group
@end example
@example
@group
        % larch my-revision-action
@end group
@group
@end group
@end example

@noindent
report the actions to be taken.


The actions have a fairly obvious meaning.  After creating a new
branch, for example, the command @code{make-branch} will invoke:

@example
@group
        % COMMAND ARGUMENTS... BRANCH
@end group
@group
@end group
@end example

@noindent
where @code{BRANCH} is a fully qualified branch name.


A useful action to take is to invoke @code{notify} directly.  Another
useful action (though imposing a greater system administration burden)
is to invoke a script which sends mail to some address, informing the
recipient of the repository change.  The recipient can be, for
example, an automated process which invokes @code{notify}.


When the repository-modifying commands invoke one of these actions,
they run the action as a @code{daemon}: an asynchronous process with no
controlling terminal, with standard input redirected from @code{/dev/null},
and with @code{stdout} and @code{stderr} saved in a temporary file.  If the
command exits with non-0 status, the output from the command is sent
to the user in an email notice.


Once again, the damn constraints of physics, particularly the
prohibition against "action at a distance", impose a constraint:  it
is impossible to guarantee the @code{COMMAND} will be invoked and in
(hopefully rare) circumstances, it might not be.  @code{COMMANDs} should be
chosen with that constraint in mind.







