@@ -237,18 +237,24 @@ type Namespace struct {
237
237
Services []IService
238
238
}
239
239
240
- // Registry represents a map of service namespaces.
241
- type Registry map [string ]Namespace
240
+ // Registry is a collection of services, organized by namespace, that preserves registration order.
241
+ type Registry struct {
242
+ namespaces map [string ]* Namespace
243
+ order []string
244
+ }
242
245
243
246
// NewServiceRegistry creates a new instance of the service registry.
244
- func NewServiceRegistry () Registry {
245
- return make (Registry )
247
+ func NewServiceRegistry () * Registry {
248
+ return & Registry {
249
+ namespaces : make (map [string ]* Namespace ),
250
+ order : make ([]string , 0 ),
251
+ }
246
252
}
247
253
248
254
// RegisterCoreService registers a core service with the given registration information.
249
255
// It calls the RegisterService method of the Registry instance with the provided registration and service type "core".
250
256
// Returns an error if the registration fails.
251
- func (reg Registry ) RegisterCoreService (svc IService ) error {
257
+ func (reg * Registry ) RegisterCoreService (svc IService ) error {
252
258
return reg .RegisterService (svc , "core" )
253
259
}
254
260
@@ -258,39 +264,48 @@ func (reg Registry) RegisterCoreService(svc IService) error {
258
264
// such as the namespace and service description.
259
265
// The mode string specifies the mode in which the service should be registered.
260
266
// It returns an error if the service is already registered in the specified namespace.
261
- func (reg Registry ) RegisterService (svc IService , mode string ) error {
262
- // Can't directly modify structs within a map, so we need to copy the namespace
263
- copyNamespace := reg [svc .GetNamespace ()]
264
- copyNamespace .Mode = mode
265
- if copyNamespace .Services == nil {
266
- copyNamespace .Services = make ([]IService , 0 )
267
+ func (reg * Registry ) RegisterService (svc IService , mode string ) error {
268
+ nsName := svc .GetNamespace ()
269
+ ns , _ := reg .GetNamespace (nsName )
270
+
271
+ if ns == nil {
272
+ ns = & Namespace {
273
+ Mode : mode ,
274
+ Services : make ([]IService , 0 ),
275
+ }
276
+ reg .namespaces [nsName ] = ns
277
+ reg .order = append (reg .order , nsName )
267
278
}
268
- found := slices .ContainsFunc (reg [svc .GetNamespace ()].Services , func (s IService ) bool {
279
+
280
+ // Check if a service with the same name is already registered in this namespace.
281
+ found := slices .ContainsFunc (ns .Services , func (s IService ) bool {
269
282
return s .GetServiceDesc ().ServiceName == svc .GetServiceDesc ().ServiceName
270
283
})
271
-
272
284
if found {
273
- return fmt .Errorf ("service already registered namespace:%s service:%s" , svc . GetNamespace () , svc .GetServiceDesc ().ServiceName )
285
+ return fmt .Errorf ("service already registered namespace:%s service:%s" , nsName , svc .GetServiceDesc ().ServiceName )
274
286
}
275
287
276
288
slog .Info (
277
289
"registered service" ,
278
- slog .String ("namespace" , svc . GetNamespace () ),
290
+ slog .String ("namespace" , nsName ),
279
291
slog .String ("service" , svc .GetServiceDesc ().ServiceName ),
280
292
)
281
- copyNamespace .Services = append (copyNamespace .Services , svc )
282
293
283
- reg [svc .GetNamespace ()] = copyNamespace
294
+ ns .Mode = mode
295
+ ns .Services = append (ns .Services , svc )
296
+ reg .namespaces [nsName ] = ns
297
+
284
298
return nil
285
299
}
286
300
287
- // Shutdown stops all the services in the service registry.
288
- // It iterates over each namespace and service in the registry,
289
- // checks if the service has a Close method and if it has been started,
290
- // and then calls the Close method to stop the service.
291
- func (reg Registry ) Shutdown () {
292
- for name , ns := range reg {
293
- for _ , svc := range ns .Services {
301
+ // Shutdown stops all the registered services in the reverse order of registration.
302
+ // If a service is started and has a Close method, the Close method will be called.
303
+ func (reg * Registry ) Shutdown () {
304
+ for nsIdx := len (reg .order ) - 1 ; nsIdx >= 0 ; nsIdx -- {
305
+ name := reg .order [nsIdx ]
306
+ ns := reg .namespaces [name ]
307
+ for serviceIdx := len (ns .Services ) - 1 ; serviceIdx >= 0 ; serviceIdx -- {
308
+ svc := ns .Services [serviceIdx ]
294
309
if svc .IsStarted () {
295
310
slog .Info ("stopping service" ,
296
311
slog .String ("namespace" , name ),
@@ -309,10 +324,18 @@ func (reg Registry) Shutdown() {
309
324
}
310
325
311
326
// GetNamespace returns the namespace with the given name from the service registry.
312
- func (reg Registry ) GetNamespace (namespace string ) (Namespace , error ) {
313
- ns , ok := reg [namespace ]
327
+ func (reg * Registry ) GetNamespace (namespace string ) (* Namespace , error ) {
328
+ ns , ok := reg . namespaces [namespace ]
314
329
if ! ok {
315
- return Namespace {} , fmt .Errorf ("namespace not found: %s" , namespace )
330
+ return nil , fmt .Errorf ("namespace not found: %s" , namespace )
316
331
}
317
332
return ns , nil
318
333
}
334
+
335
+ // GetNamespaces returns the names of the namespaces in the order they were registered.
336
+ func (reg * Registry ) GetNamespaces () []string {
337
+ // Return a copy to prevent modification of the internal order slice.
338
+ orderCopy := make ([]string , len (reg .order ))
339
+ copy (orderCopy , reg .order )
340
+ return orderCopy
341
+ }
0 commit comments