maddy

Fork https://github.com/foxcpp/maddy

git clone git://git.lin.moe/go/maddy.git

 1/*
 2Maddy Mail Server - Composable all-in-one email server.
 3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
 4
 5This program is free software: you can redistribute it and/or modify
 6it under the terms of the GNU General Public License as published by
 7the Free Software Foundation, either version 3 of the License, or
 8(at your option) any later version.
 9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program.  If not, see <https://www.gnu.org/licenses/>.
17*/
18
19package hooks
20
21import "sync"
22
23type Event int
24
25const (
26	// EventShutdown is triggered when the server process is about to stop.
27	EventShutdown Event = iota
28
29	// EventReload is triggered when the server process receives the SIGUSR2
30	// signal (on POSIX platforms) and indicates the request to reload the
31	// server configuration from persistent storage.
32	//
33	// Since it is by design problematic to reload the modules configuration,
34	// this event only applies to secondary files such as aliases mapping and
35	// TLS certificates.
36	EventReload
37
38	// EventLogRotate is triggered when the server process receives the SIGUSR1
39	// signal (on POSIX platforms) and indicates the request to reopen used log
40	// files since they might have rotated.
41	EventLogRotate
42)
43
44var (
45	hooks    = make(map[Event][]func())
46	hooksLck sync.Mutex
47)
48
49func hooksToRun(eventName Event) []func() {
50	hooksLck.Lock()
51	defer hooksLck.Unlock()
52	hooksEv := hooks[eventName]
53	if hooksEv == nil {
54		return nil
55	}
56
57	// The slice is copied so hooks can be run without holding the lock what
58	// might be important since they are likely to do a lot of I/O.
59	hooksEvCpy := make([]func(), 0, len(hooksEv))
60	hooksEvCpy = append(hooksEvCpy, hooksEv...)
61
62	return hooksEvCpy
63}
64
65// RunHooks runs the hooks installed for the specified eventName in the reverse
66// order.
67func RunHooks(eventName Event) {
68	hooks := hooksToRun(eventName)
69	for i := len(hooks) - 1; i >= 0; i-- {
70		hooks[i]()
71	}
72}
73
74// AddHook installs the hook to be executed when certain event occurs.
75func AddHook(eventName Event, f func()) {
76	hooksLck.Lock()
77	defer hooksLck.Unlock()
78
79	hooks[eventName] = append(hooks[eventName], f)
80}