@@ -748,6 +748,124 @@ fb_helpers_gated_template '/etc/foo.network' do
748748end
749749```
750750
751+ #### fb_notify_merger
752+ Use the ` fb_notify_merger ` resource to aggregate notifications and subscriptions
753+ into a single notification which fires in resource order. This solves the problem
754+ where, when multiple resources update that need to (for example) restart a service,
755+ one must currently choose between two flawed options. Either choose to
756+ notify ` :immediately ` (in which case multiple incorrect and unnecessary restarts
757+ occur), or ` :delayed ` (in which case the restarts are deduplicated, but happen
758+ out of order (at the end of the run), and create the opportunity for a (temporary)
759+ incorrectness).
760+
761+ Consider a common example. Two configuration files are inputs for a service,
762+ and updating them should cause the service to be restarted. In the initial setup
763+ scenario for a host, the service is not yet running, and we have the following
764+ recipe code:
765+
766+ ``` ruby
767+ template ' A' do
768+ ...
769+ notifies :restart , ' service[X]' , :delayed
770+ end
771+
772+ template ' B' do
773+ ...
774+ notifies :restart , ' service[X]' , :delayed
775+ end
776+
777+ service ' X' do
778+ action [:enable , :start ]
779+ end
780+ ```
781+
782+ The above code, during initial host setup, will trigger two delayed restarts, then
783+ the service will be started, then at the end of the run it will be restarted again
784+ (unnecessarily) due to the delayed notification.
785+
786+ ` fb_notify_merger ` serves as an in-order aggregation point for notifications, so
787+ that they can be deduplicated and delivered at the correct point in the run.
788+
789+ When updating the above code with the ` fb_notify_merger ` , we get:
790+
791+ ``` ruby
792+ template ' A' do
793+ ...
794+ notifies :update , ' fb_notify_merger[C]' , :immediately
795+ end
796+
797+ template ' B' do
798+ ...
799+ notifies :update , ' fb_notify_merger[C]' , :immediately
800+ end
801+
802+ fb_notify_merger ' C' do
803+ notifies :restart , ' service[X]' , :immediately
804+ end
805+
806+ service ' X' do
807+ action [:enable , :start ]
808+ end
809+ ```
810+
811+ The above code has no unnecessary restart of the service at the end of the run.
812+
813+ The ` fb_notify_merger ` resource, when running the ` :update ` action, flips a bit
814+ to true, such that when the default ` :merge ` action runs, if the
815+ bit was true, the resource is marked as updated and triggers any associated
816+ notifications.
817+
818+ ``` ruby
819+ package ' syslog' do
820+ ...
821+ notifies :update , ' fb_notify_merger[syslog]' , :immediately
822+ end
823+
824+ template ' /etc/sysconfig/syslog' do
825+ ...
826+ notifies :update , ' fb_notify_merger[syslog]' , :immediately
827+ end
828+
829+ fb_notify_merger ' syslog' do
830+ notifies :restart , " service[syslog]" , :immediately
831+ end
832+
833+ service ' syslog' do
834+ action [:enable , :start ]
835+ end
836+ ```
837+
838+ In the sample above, even if both the ` package ` and the ` template ` update, only
839+ a single ` :restart ` is issued against the ` service ` .
840+
841+ Other examples:
842+ - Two or more input files are changed in the systemd configuration. Use the
843+ ` fb_notify_merger ` to aggregate the call to ` systemctl daemon-reload ` so it
844+ only happens once, and in order.
845+ - Two or more input files for a script are changed. Use the
846+ ` fb_notify_merger ` to aggregate the ` :run ` notification for the ` execute `
847+ resource so it only happens once, and in order.
848+
849+ The ` fb_notify_merger ` resource order should be _ immediately_ before the resource
850+ which it notifies to have the most correct behavior.
851+
852+ ` notifies ` and ` subscribes ` retain the same behavior as upstream chef and both
853+ work with ` fb_notify_merger ` (though ` notifies ` is preferred since it provides stronger
854+ guarantees).
855+
856+ You must use ` :immediately ` or ` :before ` when notifying the ` fb_notify_merger `
857+ resource; if you use ` :delayed ` the in-order element is lost, and
858+ the entire point of using ` fb_notify_merger ` is lost.
859+
860+ Note that this is different from ` notify_group ` , which has no element of
861+ aggregating notifications, and only serves to minimize repetition in code.
862+
863+ Also note: ` fb_notify_merger ` tracks if it has already merged, and will
864+ fail the run if any subsequent ` :update ` or ` :merge ` actions are triggered.
865+ The ` :merge ` which triggers the actual aggregated notification should only happen
866+ a single time, immediately before the resource which is being notified; all
867+ other flows are fundamentally flawed.
868+
751869### Reboot control
752870If it's safe for Chef to reboot your host, set ` reboot_allowed ` to true in
753871your cookbook:
0 commit comments