github.com/polarismesh/polaris@v1.17.8/common/eventhub/eventhub.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package eventhub 19 20 import ( 21 "context" 22 "errors" 23 "sync" 24 ) 25 26 var ( 27 initOnce sync.Once 28 globalEventHub *eventHub 29 ) 30 31 var ( 32 ErrorEventhubNotInitialize = errors.New("eventhub not initialize") 33 ) 34 35 // InitEventHub initialize event hub 36 func InitEventHub() { 37 initOnce.Do(func() { 38 globalEventHub = createEventhub() 39 }) 40 } 41 42 func createEventhub() *eventHub { 43 ctx, cancel := context.WithCancel(context.Background()) 44 return &eventHub{ 45 ctx: ctx, 46 cancel: cancel, 47 topics: make(map[string]*topic), 48 } 49 } 50 51 // Event evnt type 52 type Event interface{} 53 54 // eventHub event hub 55 type eventHub struct { 56 ctx context.Context 57 cancel context.CancelFunc 58 topics map[string]*topic 59 mu sync.RWMutex 60 } 61 62 // Publish pushlish event to topic 63 // @param topic Topic name 64 // @param event Event object 65 func Publish(topic string, event Event) error { 66 if globalEventHub == nil { 67 return ErrorEventhubNotInitialize 68 } 69 return globalEventHub.Publish(topic, event) 70 } 71 72 func (eh *eventHub) Publish(topic string, event Event) error { 73 t := eh.getTopic(topic) 74 t.publish(eh.ctx, event) 75 return nil 76 } 77 78 // Subscribe subscribe topic 79 // @param topic Topic name 80 // @param name Subscribe name 81 // @param handler Message handler 82 // @param opts Subscription options 83 // @return error Subscribe failed, return error 84 func Subscribe(topic string, handler Handler, opts ...SubOption) (*SubscribtionContext, error) { 85 if globalEventHub == nil { 86 return nil, ErrorEventhubNotInitialize 87 } 88 return globalEventHub.Subscribe(topic, handler, opts...) 89 } 90 91 func (e *eventHub) Subscribe(topic string, handler Handler, 92 opts ...SubOption) (*SubscribtionContext, error) { 93 t := e.getTopic(topic) 94 return t.subscribe(e.ctx, handler, opts...) 95 } 96 97 // Shutdown shutdown event hub 98 func Shutdown() { 99 if globalEventHub == nil { 100 return 101 } 102 globalEventHub.shutdown() 103 } 104 105 func (e *eventHub) shutdown() { 106 e.mu.Lock() 107 defer e.mu.Unlock() 108 109 e.cancel() 110 for _, t := range e.topics { 111 t.close(e.ctx) 112 delete(e.topics, t.name) 113 } 114 } 115 116 func (e *eventHub) createTopic(name string) *topic { 117 e.mu.Lock() 118 defer e.mu.Unlock() 119 if t, ok := e.topics[name]; ok { 120 return t 121 } 122 t := newTopic(name) 123 e.topics[name] = t 124 go t.run(e.ctx) 125 return t 126 } 127 128 func (e *eventHub) getTopic(name string) *topic { 129 e.mu.RLock() 130 if t, ok := e.topics[name]; ok { 131 e.mu.RUnlock() 132 return t 133 } 134 e.mu.RUnlock() 135 return e.createTopic(name) 136 }