Go 为事件处理程序的多个实例创建包装器
我正试图解决一个有关频道使用和正确处理这些频道的问题(很可能是设计问题)。 我正在使用Knative事件/云事件来创建和处理事件管道 我希望能够处理不同的通道,以便接收来自不同来源/方法的事件 为了做到这一点,我有下面的实现(代码已被删除,以便简洁地详细说明问题) 我有一个Go 为事件处理程序的多个实例创建包装器,go,wrapper,channel,knative,Go,Wrapper,Channel,Knative,我正试图解决一个有关频道使用和正确处理这些频道的问题(很可能是设计问题)。 我正在使用Knative事件/云事件来创建和处理事件管道 我希望能够处理不同的通道,以便接收来自不同来源/方法的事件 为了做到这一点,我有下面的实现(代码已被删除,以便简洁地详细说明问题) 我有一个file1.go,它定义了一个EventHandler结构、关联的方法和两个导出的方法(CreatePreview()和SaveAndPublish()),这是应用程序的“正常”行为,实际接收/处理频道上的任何值: type
file1.go
,它定义了一个EventHandler
结构、关联的方法和两个导出的方法(CreatePreview()
和SaveAndPublish()
),这是应用程序的“正常”行为,实际接收/处理频道上的任何值:
type EventHandler struct {
Channel chan string
}
func (ev *EventHandler) Handle(event cloudevents.Event) {
if event.Data == nil {
(...)
}
var data string
if err := event.DataAs(&data); err != nil {
(...)
}
ev.Channel <- data
defer close(ev.Channel)
}
func (ev *EventHandler) Create(param *Element) (error) {
(...) //Unimportant code
}
func (repo *Repository) CreatePreview(param1 string, param2 string, eventHandler *EventHandler) (*pb.PreviewResponse, error) {
(...)
err := eventHandler.Create(&document)
(...)
preview := <- eventHandler.Channel
(...)
}
func (repo *Repository) SaveAndPublish(param1 string, param2 bool, eventHandler *EventHandler) (*pb.PublishResponse, error) {
(...)
err := eventHandler.Create(&documentToUpdate)
(...)
published := <- eventHandler.Channel
(...)
return repo.SomeOtherMethod(published.ID)
}
现在,我知道,为了使用c.StartReceiver()上的eventHandler.Handle
方法main.go上的c.StartReceiver()
,我不必实例化单个全局eventHandler
,我可以定义一个可能包含事件处理程序列表的包装器(HandlerWrapper())main.go上的方法
但是,我不知道如何识别EventHandler
的哪个实例,以及如何正确处理和路由这些操作,这就是我的问题:
在这种情况下,我想创建一个包装器(一个传递到c.StartReceive()
)中的单个函数),然后让它由Handle()的正确实例处理,该如何处理
我希望问题是清楚的。我已经想了好几天了,不知道该怎么做。大概,您应该能够通过使用来自该事件的不同来源/方法来区分事件。例如,快速查看可以根据源划分为多个频道的节目
我看到这里没有使用的主要内容是上下文对象。你似乎可以从这个背景中找到来源。这可以在他们的示例中看到(查看receive函数)
例如:
// these are all the handlers for the different sources.
type EventHandlers map[string]CloudEventHandler
var _eventHandlerKey = "cloudEventHandlers"
func HandlerWrapper(ctx context.Context, event cloudevents.Event) {
// Get event source from event context.
src := event.Context.Source
// Then get the appropriate handler for that source (attached to context).
handler := ctx.Value(_eventHandlers).(Values)[src]
// ex: src = "/foo"
handler.SendToChannel(event)
}
func main() {
eventHandlers := make(map[string]CloudEventHandler)
// create all the channels we need, add it to the context.
for _, source := range sourceTypes { // foo bar baz
handler := NewHandler(source)
eventHandlers[source] = handler
}
// start HTTP server
go func() {
// Add the handlers to the context.
context := context.WithValue(context.Background(), _eventHandlerKey, eventHandlers)
log.Fatal(c.StartReceiver(context.Background(), HandlerWrapper))
}
}()
如果有3个不同的源需要支持,您可以使用来实例化这些不同的通道和所有这些实现的接口
// CloudEventHandler Handles sending cloud events to the proper channel for processing.
type CloudEventHandler interface {
SendToChannel(cloudEvents.Event)
}
type fooHandler struct {channel chan string}
type barHandler struct {channel chan int}
type bazHandler struct {channel chan bool}
func NewHandler(source string) CloudEventHandler {
switch source {
case "/foo":
return &fooHandler{channel: make(chan string, 2)} // buffered channel
case "/bar":
return &barHandler{channel: make(chan int, 2)}
case "/baz":
return &bazHandler{channel: make(chan bool, 2)}
}
}
func (fh *fooHandler) SendToChannel(event CloudEvents.Event) {
var data string
if err := event.DataAs(&data); err != nil {
// (...)
}
go func() {
fh.channel <- data
}()
}
func (bh *barHandler) SendToChannel(event CloudEvents.Event) {
var data int
if err := event.DataAs(&data); err != nil {
// (...)
}
go func() {
bh.channel <- data
}()
}
//CloudEventHandler处理将云事件发送到适当的通道进行处理的问题。
类型CloudEventHandler接口{
SendToChannel(cloudEvents.Event)
}
类型foodhandler结构{channel chan string}
类型barHandler结构{channel chan int}
类型bazHandler结构{channel chan bool}
func NewHandler(源字符串)CloudEventHandler{
开关电源{
案例“/foo”:
return&foodhandler{channel:make(chan string,2)}//缓冲通道
案例“/bar”:
return&barHandler{channel:make(chan int,2)}
案例“/baz”:
返回和返回{通道:make(chan bool,2)}
}
}
func(fh*foodhandler)SendToChannel(event CloudEvents.event){
变量数据字符串
如果错误:=event.DataAs(&data);错误!=nil{
// (...)
}
go func(){
跳频信道
// CloudEventHandler Handles sending cloud events to the proper channel for processing.
type CloudEventHandler interface {
SendToChannel(cloudEvents.Event)
}
type fooHandler struct {channel chan string}
type barHandler struct {channel chan int}
type bazHandler struct {channel chan bool}
func NewHandler(source string) CloudEventHandler {
switch source {
case "/foo":
return &fooHandler{channel: make(chan string, 2)} // buffered channel
case "/bar":
return &barHandler{channel: make(chan int, 2)}
case "/baz":
return &bazHandler{channel: make(chan bool, 2)}
}
}
func (fh *fooHandler) SendToChannel(event CloudEvents.Event) {
var data string
if err := event.DataAs(&data); err != nil {
// (...)
}
go func() {
fh.channel <- data
}()
}
func (bh *barHandler) SendToChannel(event CloudEvents.Event) {
var data int
if err := event.DataAs(&data); err != nil {
// (...)
}
go func() {
bh.channel <- data
}()
}