@@ -81,15 +81,21 @@ type Config struct {
81
81
// ClientConnectionRateLimit sets the maximum number of new connections a single Centrifugo
82
82
// node will accept per second.
83
83
ClientConnectionRateLimit int
84
+
85
+ // GlobalHistoryMetaTTL from here is used only for validation.
86
+ GlobalHistoryMetaTTL time.Duration
84
87
}
85
88
89
+ const DefaultGlobalHistoryMetaTTL = 30 * 24 * time .Hour
90
+
86
91
// DefaultConfig has default config options.
87
92
var DefaultConfig = Config {
88
93
ChannelPrivatePrefix : "$" , // so private channel will look like "$gossips".
89
94
ChannelNamespaceBoundary : ":" , // so namespace "public" can be used as "public:news".
90
95
ChannelUserBoundary : "#" , // so user limited channel is "user#2694" where "2696" is user ID.
91
96
ChannelUserSeparator : "," , // so several users limited channel is "dialog#2694,3019".
92
97
RpcNamespaceBoundary : ":" , // so rpc namespace "chat" can be used as "chat:get_user_info".
98
+ GlobalHistoryMetaTTL : DefaultGlobalHistoryMetaTTL ,
93
99
}
94
100
95
101
func stringInSlice (a string , list []string ) bool {
@@ -104,13 +110,13 @@ func stringInSlice(a string, list []string) bool {
104
110
var namePattern = "^[-a-zA-Z0-9_.]{2,}$"
105
111
var nameRe = regexp .MustCompile (namePattern )
106
112
107
- func ValidateNamespace (ns ChannelNamespace ) error {
113
+ func ValidateNamespace (ns ChannelNamespace , globalHistoryMetaTTL time. Duration ) error {
108
114
name := ns .Name
109
115
match := nameRe .MatchString (name )
110
116
if ! match {
111
117
return fmt .Errorf ("invalid namespace name – %s (must match %s regular expression)" , name , namePattern )
112
118
}
113
- if err := ValidateChannelOptions (ns .ChannelOptions ); err != nil {
119
+ if err := ValidateChannelOptions (ns .ChannelOptions , globalHistoryMetaTTL ); err != nil {
114
120
return err
115
121
}
116
122
return nil
@@ -128,10 +134,17 @@ func ValidateRpcNamespace(ns RpcNamespace) error {
128
134
return nil
129
135
}
130
136
131
- func ValidateChannelOptions (c ChannelOptions ) error {
137
+ func ValidateChannelOptions (c ChannelOptions , globalHistoryMetaTTL time. Duration ) error {
132
138
if (c .HistorySize != 0 && c .HistoryTTL == 0 ) || (c .HistorySize == 0 && c .HistoryTTL != 0 ) {
133
139
return errors .New ("both history size and history ttl required for history" )
134
140
}
141
+ historyMetaTTL := globalHistoryMetaTTL
142
+ if c .HistoryMetaTTL != 0 {
143
+ historyMetaTTL = time .Duration (c .HistoryMetaTTL )
144
+ }
145
+ if historyMetaTTL < time .Duration (c .HistoryTTL ) {
146
+ return fmt .Errorf ("history ttl (%s) can not be greater than history meta ttl (%s)" , time .Duration (c .HistoryTTL ), historyMetaTTL )
147
+ }
135
148
if c .ForceRecovery && (c .HistorySize == 0 || c .HistoryTTL == 0 ) {
136
149
return errors .New ("both history size and history ttl required for recovery" )
137
150
}
@@ -152,7 +165,7 @@ func ValidateRpcOptions(_ RpcOptions) error {
152
165
153
166
// Validate validates config and returns error if problems found
154
167
func (c * Config ) Validate () error {
155
- if err := ValidateChannelOptions (c .ChannelOptions ); err != nil {
168
+ if err := ValidateChannelOptions (c .ChannelOptions , c . GlobalHistoryMetaTTL ); err != nil {
156
169
return err
157
170
}
158
171
if err := ValidateRpcOptions (c .RpcOptions ); err != nil {
@@ -175,7 +188,7 @@ func (c *Config) Validate() error {
175
188
if stringInSlice (n .Name , nss ) {
176
189
return fmt .Errorf ("namespace name must be unique: %s" , n .Name )
177
190
}
178
- if err := ValidateNamespace (n ); err != nil {
191
+ if err := ValidateNamespace (n , c . GlobalHistoryMetaTTL ); err != nil {
179
192
return fmt .Errorf ("namespace %s: %v" , n .Name , err )
180
193
}
181
194
if n .Name == personalChannelNamespace {
0 commit comments