From 78c19be63a44538713c93934ccdbae6f6fe639b4 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Thu, 15 Oct 2020 10:35:59 +0100 Subject: [PATCH 1/6] Chat Service Proto --- chat/proto/chat.proto | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 chat/proto/chat.proto diff --git a/chat/proto/chat.proto b/chat/proto/chat.proto new file mode 100644 index 0000000..8670b78 --- /dev/null +++ b/chat/proto/chat.proto @@ -0,0 +1,58 @@ +syntax = "proto3"; + +package chat; +option go_package = "github.com/micro/services/chat;chat"; + +service Chat { + // New creates a chat for a group of users. The RPC is idempotent so if it's called multiple times + // for the same users, the same response will be returned. It's good practice to design APIs as + // idempotent since this enables safe retries. + rpc New(NewRequest) returns (NewResponse); + // History returns the historical messages in a chat + rpc History(HistoryRequest) returns (HistoryResponse); + // Connect to a chat using a bidirectional stream enabling the client to send and recieve messages + // over a single RPC. When a message is sent on the stream, it will be added to the chat history + // and sent to the other connected users. When opening the connection, the client should provide + // the chat_id and user_id in the context so the server knows which messages to stream. + rpc Connect(stream Message) returns (stream Message); +} + +// NewRequest contains the infromation needed to create a new chat +message NewRequest { + repeated string user_ids = 1; +} + +// NewResponse contains the chat id for the users +message NewResponse { + string chat_id = 1; +} + +// HistoryRequest contains the id of the chat we want the history for. This RPC will return all +// historical messages, however in a real life application we'd introduce some form of pagination +// here, only loading the older messages when required. +message HistoryRequest { + string chat_id = 1; +} + +// HistoryResponse contains the historical messages in a chat +message HistoryResponse { + repeated Message messages = 1; +} + +// Message sent to a chat +message Message { + // id of the message, allocated by the server + string id = 1; + // a client side id, should be validated by the server to make the request retry safe + string client_id = 2; + // id of the chat the message is being sent to / from + string chat_id = 3; + // id of the user who sent the message + string user_id = 4; + // time time the message was sent in unix format + int32 sent_at = 5; + // subject of the message + string subject = 6; + // text of the message + string text = 7; +} \ No newline at end of file From 68f3e526560fe4cc0462b8a9abd9c6b1bdf316c3 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Thu, 15 Oct 2020 12:28:27 +0100 Subject: [PATCH 2/6] Chat Handler --- chat/handler/handler.go | 244 ++++++++++++++++++++++++++++ chat/main.go | 25 +++ chat/proto/chat.pb.go | 314 ++++++++++++++++++++++++++++++++++++ chat/proto/chat.pb.micro.go | 225 ++++++++++++++++++++++++++ chat/proto/chat.proto | 2 +- go.mod | 5 +- go.sum | 3 + 7 files changed, 814 insertions(+), 4 deletions(-) create mode 100644 chat/handler/handler.go create mode 100644 chat/main.go create mode 100644 chat/proto/chat.pb.go create mode 100644 chat/proto/chat.pb.micro.go diff --git a/chat/handler/handler.go b/chat/handler/handler.go new file mode 100644 index 0000000..b6e2527 --- /dev/null +++ b/chat/handler/handler.go @@ -0,0 +1,244 @@ +package handler + +import ( + "context" + "sort" + "strings" + + "github.com/micro/micro/v3/service/context/metadata" + + // import the proto, it's standard to import the services own proto under the alias pb + "github.com/google/uuid" + "github.com/micro/micro/v3/service/errors" + "github.com/micro/micro/v3/service/events" + "github.com/micro/micro/v3/service/logger" + "github.com/micro/micro/v3/service/store" + pb "github.com/micro/services/chat/proto" +) + +// New returns an initialized chat handler +func New() pb.ChatHandler { + return new(handler) +} + +const ( + storeKeyPrefix = "chat/" + eventKeyPrefix = "chat/" +) + +// handler satisfies the ChatHandler interface. You can see this inteface defined in chat.pb.micro.go +type handler struct{} + +// New creates a chat for a group of users. The RPC is idempotent so if it's called multiple times +// for the same users, the same response will be returned. It's good practice to design APIs as +// idempotent since this enables safe retries. +func (h *handler) New(ctx context.Context, req *pb.NewRequest, rsp *pb.NewResponse) error { + // in a real world application we would authorize the request to ensure the authenticated user + // is part of the chat they're attempting to create. We could do this by getting the user id from + // auth.AccountFromContext(ctx) and then validating the presence of their id in req.UserIds. If + // the user is not part of the request then we'd return a Forbidden error, which the micro api + // would transform to a 403 status code. + + // validate the request + if len(req.UserIds) == 0 { + // Return a bad request error to the client, the first argument is a unique id which the client + // can check for. The second argument is a human readable description. Returning the correct type + // of error is important as it's used by the network to know if a request should be retried. Only + // 500 (InternalServerError) and 408 (Timeout) errors are retried. + return errors.BadRequest("chat.New.MissingUserIDs", "One or more user IDs are required") + } + + // construct a key to identify the chat, we'll do this by sorting the user ids alphabetically and + // then joining them. When a service calls the store, the data returned will be automatically scoped + // to the service however it's still advised to use a prefix when writing data since this allows + // other types of keys to be written in the future. We'll make a copy of the req.UserIds object as + // it's a good practice to not mutate the request object. + sortedIDs := make([]string, len(req.UserIds)) + copy(sortedIDs, req.UserIds) + sort.Strings(sortedIDs) + + // key to lookup the chat in the store using, e.g. "chat/usera-userb-userc" + key := storeKeyPrefix + strings.Join(sortedIDs, "-") + + // read from the store to check if a chat with these users already exists + recs, err := store.Read(key) + if err != nil { + // if an error wasn't returned, at least one record was found. The value returned by the store + // is the bytes representation of the chat id. We'll convert this back into a string and return + // it to the client. + rsp.ChatId = string(recs[0].Value) + return nil + } else if err != store.ErrNotFound { + // if no records were found then we'd expect to get a store.ErrNotFound error returned. If this + // wasn't the case, the service could've experienced an issue connecting to the store so we should + // log the error and return an InternalServerError to the client, indicating the request should + // be retried + logger.Errorf("Error reading from the store. Key: %v. Error: %v", key, err) + return errors.InternalServerError("chat.New.Unknown", "Error reading from the store") + } + + // no chat id was returned so we'll generate one, write it to the store and then return it to the + // client + chatID := uuid.New().String() + record := store.Record{Key: key, Value: []byte(chatID)} + if err := store.Write(&record); err != nil { + logger.Errorf("Error writing to the store. Key: %v. Error: %v", key, err) + return errors.InternalServerError("chat.New.Unknown", "Error writing to the store") + } + + // The chat was successfully created so we'll log the event and then return the id to the client. + // Note that we'll use logger.Infof here vs the Errorf above. + logger.Infof("New chat created with ID %v", chatID) + rsp.ChatId = chatID + return nil +} + +// History returns the historical messages in a chat +func (h *handler) History(ctx context.Context, req *pb.HistoryRequest, rsp *pb.HistoryResponse) error { + // as per the New function, in a real world application we would authorize the request to ensure + // the authenticated user is part of the chat they're attempting to read the history of + + // validate the request + if len(req.ChatId) == 0 { + return errors.BadRequest("chat.History.MissingChatID", "ChatID is missing") + } + + // lookup the chat from the store to ensure it's valid + if _, err := store.Read(storeKeyPrefix + req.ChatId); err == store.ErrNotFound { + return errors.BadRequest("chat.History.InvalidChatID", "Chat not found with this ID") + } else if err != nil { + logger.Errorf("Error reading from the store. Chat ID: %v. Error: %v", req.ChatId, err) + return errors.InternalServerError("chat.History.Unknown", "Error reading from the store") + } + + // lookup the historical messages for the chat using the event store. lots of packages in micro + // support options, in this case we'll pass the ReadLimit option to restrict the number of messages + // we'll load from the events store. + messages, err := events.Read(eventKeyPrefix+req.ChatId, events.ReadLimit(50)) + if err != nil { + logger.Errorf("Error reading from the event store. Chat ID: %v. Error: %v", req.ChatId, err) + return errors.InternalServerError("chat.History.Unknown", "Error reading from the event store") + } + + // we've loaded the messages from the event store. next we need to serialize them and return them + // to the client. The message is stored in the event payload, to retrieve it we need to unmarshal + // the event into a message struct. + rsp.Messages = make([]*pb.Message, len(messages)) + for i, ev := range messages { + var msg pb.Message + if err := ev.Unmarshal(&msg); err != nil { + logger.Errorf("Error unmarshaling event: %v", err) + return errors.InternalServerError("chat.History.Unknown", "Error unmarshaling event") + } + rsp.Messages[i] = &msg + } + + return nil +} + +// Connect to a chat using a bidirectional stream enabling the client to send and recieve messages +// over a single RPC. When a message is sent on the stream, it will be added to the chat history +// and sent to the other connected users. When opening the connection, the client should provide +// the chat_id and user_id in the context so the server knows which messages to stream. +func (h *handler) Connect(ctx context.Context, stream pb.Chat_ConnectStream) error { + // the client passed the chat id and user id in the request context. we'll load that information + // now and validate it. If any information is missing we'll return a BadRequest error to the client + userID, ok := metadata.Get(ctx, "UserID") + if !ok { + return errors.BadRequest("chat.Connect.MissingUserID", "UserID missing in context") + } + chatID, ok := metadata.Get(ctx, "ChatID") + if !ok { + return errors.BadRequest("chat.Connect.MissingChatID", "ChatId missing in context") + } + + // lookup the chat from the store to ensure it's valid + if _, err := store.Read(storeKeyPrefix + chatID); err == store.ErrNotFound { + return errors.BadRequest("chat.Connect.InvalidChatID", "Chat not found with this ID") + } else if err != nil { + logger.Errorf("Error reading from the store. Chat ID: %v. Error: %v", chatID, err) + return errors.InternalServerError("chat.Connect.Unknown", "Error reading from the store") + } + + // as per the New and Connect functions, at this point in a real world application we would + // authorize the request to ensure the authenticated user is part of the chat they're attempting + // to read the history of + + // create a new context which can be cancelled, in the case either the consumer of publisher errors + // we don't want one to keep running in the background + cancelCtx, cancel := context.WithCancel(ctx) + defer cancel() + + // create a channel to send errors on, because the subscriber / publisher will run in seperate go- + // routines, they need a way of returning errors to the client + errChan := make(chan error) + + // create an event stream to consume messages posted by other users into the chat. we'll use the + // user id as a queue to ensure each user recieves the message + evStream, err := events.Subscribe(eventKeyPrefix+chatID, events.WithQueue(userID)) + if err != nil { + defer cancel() + logger.Errorf("Error streaming events. Chat ID: %v. Error: %v", chatID, err) + return errors.InternalServerError("chat.Connect.Unknown", "Error connecting to the event stream") + } + go func() { + for { + select { + case <-cancelCtx.Done(): + // the context has been cancelled or timed out, stop subscribing to new messages + return + case ev := <-evStream: + // recieved a message, unmarshal it into a message struct. if an error occurs log it and + // cancel the context + var msg pb.Message + if err := ev.Unmarshal(&msg); err != nil { + logger.Errorf("Error unmarshaling message. ChatID: %v. Error: %v", chatID, err) + errChan <- err + return + } + + // ignore any messages published by the current user + if msg.UserId == userID { + continue + } + + // publish the message to the stream + if err := stream.Send(&msg); err != nil { + logger.Errorf("Error sending message to stream. ChatID: %v. Message ID: %v. Error: %v", chatID, msg.Id, err) + errChan <- err + return + } + } + } + }() + + // transform the stream.Recv into a channel which can be used in the select statement below + msgChan := make(chan *pb.Message) + go func() { + for { + msg, err := stream.Recv() + if err != nil { + errChan <- err + close(msgChan) + return + } + msgChan <- msg + } + }() + + for { + select { + case <-cancelCtx.Done(): + // the context has been cancelled or timed out, stop subscribing to new messages + return nil + case err := <-errChan: + // an error occured in another goroutine, terminate the stream + return err + case msg := <-msgChan: + // a message was recieved from the client, send it to the event stream + if err := events.Publish(eventKeyPrefix+chatID, msg); err != nil { + return err + } + } + } +} diff --git a/chat/main.go b/chat/main.go new file mode 100644 index 0000000..46d608b --- /dev/null +++ b/chat/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "github.com/micro/micro/v3/service" + "github.com/micro/micro/v3/service/logger" + + "github.com/micro/services/chat/handler" + pb "github.com/micro/services/chat/proto" +) + +func main() { + // Create the service + srv := service.New( + service.Name("chat"), + service.Version("latest"), + ) + + // Register the handler against the server + pb.RegisterChatHandler(srv.Server(), handler.New()) + + // Run the service + if err := srv.Run(); err != nil { + logger.Fatal(err) + } +} diff --git a/chat/proto/chat.pb.go b/chat/proto/chat.pb.go new file mode 100644 index 0000000..e67ba30 --- /dev/null +++ b/chat/proto/chat.pb.go @@ -0,0 +1,314 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: proto/chat.proto + +package chat + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// NewRequest contains the infromation needed to create a new chat +type NewRequest struct { + UserIds []string `protobuf:"bytes,1,rep,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NewRequest) Reset() { *m = NewRequest{} } +func (m *NewRequest) String() string { return proto.CompactTextString(m) } +func (*NewRequest) ProtoMessage() {} +func (*NewRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_ed7e7dde45555b7d, []int{0} +} + +func (m *NewRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NewRequest.Unmarshal(m, b) +} +func (m *NewRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NewRequest.Marshal(b, m, deterministic) +} +func (m *NewRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NewRequest.Merge(m, src) +} +func (m *NewRequest) XXX_Size() int { + return xxx_messageInfo_NewRequest.Size(m) +} +func (m *NewRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NewRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NewRequest proto.InternalMessageInfo + +func (m *NewRequest) GetUserIds() []string { + if m != nil { + return m.UserIds + } + return nil +} + +// NewResponse contains the chat id for the users +type NewResponse struct { + ChatId string `protobuf:"bytes,1,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NewResponse) Reset() { *m = NewResponse{} } +func (m *NewResponse) String() string { return proto.CompactTextString(m) } +func (*NewResponse) ProtoMessage() {} +func (*NewResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ed7e7dde45555b7d, []int{1} +} + +func (m *NewResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NewResponse.Unmarshal(m, b) +} +func (m *NewResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NewResponse.Marshal(b, m, deterministic) +} +func (m *NewResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NewResponse.Merge(m, src) +} +func (m *NewResponse) XXX_Size() int { + return xxx_messageInfo_NewResponse.Size(m) +} +func (m *NewResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NewResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NewResponse proto.InternalMessageInfo + +func (m *NewResponse) GetChatId() string { + if m != nil { + return m.ChatId + } + return "" +} + +// HistoryRequest contains the id of the chat we want the history for. This RPC will return all +// historical messages, however in a real life application we'd introduce some form of pagination +// here, only loading the older messages when required. +type HistoryRequest struct { + ChatId string `protobuf:"bytes,1,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HistoryRequest) Reset() { *m = HistoryRequest{} } +func (m *HistoryRequest) String() string { return proto.CompactTextString(m) } +func (*HistoryRequest) ProtoMessage() {} +func (*HistoryRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_ed7e7dde45555b7d, []int{2} +} + +func (m *HistoryRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HistoryRequest.Unmarshal(m, b) +} +func (m *HistoryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HistoryRequest.Marshal(b, m, deterministic) +} +func (m *HistoryRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_HistoryRequest.Merge(m, src) +} +func (m *HistoryRequest) XXX_Size() int { + return xxx_messageInfo_HistoryRequest.Size(m) +} +func (m *HistoryRequest) XXX_DiscardUnknown() { + xxx_messageInfo_HistoryRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_HistoryRequest proto.InternalMessageInfo + +func (m *HistoryRequest) GetChatId() string { + if m != nil { + return m.ChatId + } + return "" +} + +// HistoryResponse contains the historical messages in a chat +type HistoryResponse struct { + Messages []*Message `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HistoryResponse) Reset() { *m = HistoryResponse{} } +func (m *HistoryResponse) String() string { return proto.CompactTextString(m) } +func (*HistoryResponse) ProtoMessage() {} +func (*HistoryResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ed7e7dde45555b7d, []int{3} +} + +func (m *HistoryResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HistoryResponse.Unmarshal(m, b) +} +func (m *HistoryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HistoryResponse.Marshal(b, m, deterministic) +} +func (m *HistoryResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_HistoryResponse.Merge(m, src) +} +func (m *HistoryResponse) XXX_Size() int { + return xxx_messageInfo_HistoryResponse.Size(m) +} +func (m *HistoryResponse) XXX_DiscardUnknown() { + xxx_messageInfo_HistoryResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_HistoryResponse proto.InternalMessageInfo + +func (m *HistoryResponse) GetMessages() []*Message { + if m != nil { + return m.Messages + } + return nil +} + +// Message sent to a chat +type Message struct { + // id of the message, allocated by the server + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // a client side id, should be validated by the server to make the request retry safe + ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + // id of the chat the message is being sent to / from + ChatId string `protobuf:"bytes,3,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"` + // id of the user who sent the message + UserId string `protobuf:"bytes,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + // time time the message was sent in unix format + SentAt int32 `protobuf:"varint,5,opt,name=sent_at,json=sentAt,proto3" json:"sent_at,omitempty"` + // subject of the message + Subject string `protobuf:"bytes,6,opt,name=subject,proto3" json:"subject,omitempty"` + // text of the message + Text string `protobuf:"bytes,7,opt,name=text,proto3" json:"text,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_ed7e7dde45555b7d, []int{4} +} + +func (m *Message) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Message.Unmarshal(m, b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) +} +func (m *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return xxx_messageInfo_Message.Size(m) +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +func (m *Message) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *Message) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *Message) GetChatId() string { + if m != nil { + return m.ChatId + } + return "" +} + +func (m *Message) GetUserId() string { + if m != nil { + return m.UserId + } + return "" +} + +func (m *Message) GetSentAt() int32 { + if m != nil { + return m.SentAt + } + return 0 +} + +func (m *Message) GetSubject() string { + if m != nil { + return m.Subject + } + return "" +} + +func (m *Message) GetText() string { + if m != nil { + return m.Text + } + return "" +} + +func init() { + proto.RegisterType((*NewRequest)(nil), "chat.NewRequest") + proto.RegisterType((*NewResponse)(nil), "chat.NewResponse") + proto.RegisterType((*HistoryRequest)(nil), "chat.HistoryRequest") + proto.RegisterType((*HistoryResponse)(nil), "chat.HistoryResponse") + proto.RegisterType((*Message)(nil), "chat.Message") +} + +func init() { proto.RegisterFile("proto/chat.proto", fileDescriptor_ed7e7dde45555b7d) } + +var fileDescriptor_ed7e7dde45555b7d = []byte{ + // 351 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0x41, 0x4f, 0xf2, 0x40, + 0x10, 0xcd, 0x42, 0x69, 0x61, 0xc8, 0xc7, 0x87, 0x1b, 0x8d, 0x2b, 0x5e, 0x48, 0x0f, 0x5a, 0x24, + 0xa1, 0x06, 0x13, 0x2f, 0x7a, 0x51, 0x2e, 0x72, 0x90, 0x43, 0x8f, 0x5e, 0x48, 0x69, 0x37, 0xb0, + 0x46, 0xba, 0xd8, 0xd9, 0x8a, 0xfe, 0x12, 0x7f, 0x86, 0x7f, 0xd1, 0xec, 0x6e, 0x41, 0x30, 0xf1, + 0x36, 0xef, 0xbd, 0x99, 0xd9, 0x37, 0x2f, 0x0b, 0xed, 0x55, 0x2e, 0x95, 0x0c, 0x93, 0x45, 0xac, + 0x06, 0xa6, 0xa4, 0x8e, 0xae, 0xfd, 0x73, 0x80, 0x09, 0x5f, 0x47, 0xfc, 0xb5, 0xe0, 0xa8, 0xe8, + 0x09, 0xd4, 0x0b, 0xe4, 0xf9, 0x54, 0xa4, 0xc8, 0x48, 0xb7, 0x1a, 0x34, 0x22, 0x4f, 0xe3, 0x71, + 0x8a, 0xfe, 0x19, 0x34, 0x4d, 0x23, 0xae, 0x64, 0x86, 0x9c, 0x1e, 0x83, 0xa7, 0xe7, 0xa7, 0x22, + 0x65, 0xa4, 0x4b, 0x82, 0x46, 0xe4, 0x6a, 0x38, 0x4e, 0xfd, 0x1e, 0xb4, 0x1e, 0x04, 0x2a, 0x99, + 0x7f, 0x6c, 0x96, 0xfe, 0xd9, 0x7a, 0x0b, 0xff, 0xb7, 0xad, 0xe5, 0xda, 0x1e, 0xd4, 0x97, 0x1c, + 0x31, 0x9e, 0x73, 0x6b, 0xa0, 0x39, 0xfc, 0x37, 0x30, 0x9e, 0x1f, 0x2d, 0x1b, 0x6d, 0x65, 0xff, + 0x8b, 0x80, 0x57, 0xb2, 0xb4, 0x05, 0x95, 0xed, 0xf6, 0x8a, 0x48, 0xe9, 0x29, 0x34, 0x92, 0x17, + 0xc1, 0x33, 0xf3, 0x68, 0xc5, 0xd0, 0x75, 0x4b, 0x8c, 0xd3, 0x5d, 0x3f, 0xd5, 0x5d, 0x3f, 0x5a, + 0x28, 0xaf, 0x67, 0x8e, 0x15, 0xec, 0xf1, 0x5a, 0x40, 0xbd, 0x2c, 0x56, 0xac, 0xd6, 0x25, 0x41, + 0x2d, 0x72, 0x35, 0xbc, 0x53, 0x94, 0x81, 0x87, 0xc5, 0xec, 0x99, 0x27, 0x8a, 0xb9, 0x66, 0x62, + 0x03, 0x29, 0x05, 0x47, 0xf1, 0x77, 0xc5, 0x3c, 0x43, 0x9b, 0x7a, 0xf8, 0x49, 0xc0, 0x19, 0x2d, + 0x62, 0x45, 0x2f, 0xa0, 0x3a, 0xe1, 0x6b, 0xda, 0xb6, 0xa7, 0xfd, 0xe4, 0xdf, 0x39, 0xd8, 0x61, + 0xca, 0x44, 0xae, 0xc1, 0x2b, 0x43, 0xa2, 0x87, 0x56, 0xdd, 0x8f, 0xb7, 0x73, 0xf4, 0x8b, 0x2d, + 0xe7, 0xfa, 0xe0, 0x8d, 0x64, 0x96, 0x69, 0x2f, 0xfb, 0x11, 0x76, 0xf6, 0x61, 0x40, 0x2e, 0xc9, + 0x7d, 0xff, 0xa9, 0x37, 0x17, 0x6a, 0x51, 0xcc, 0x06, 0x89, 0x5c, 0x86, 0x4b, 0x91, 0xe4, 0x32, + 0x44, 0x9e, 0xbf, 0x89, 0x84, 0xa3, 0xf9, 0x33, 0xa1, 0xf9, 0x33, 0x37, 0xba, 0x9c, 0xb9, 0xa6, + 0xbe, 0xfa, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x71, 0x1b, 0x44, 0xc0, 0x53, 0x02, 0x00, 0x00, +} diff --git a/chat/proto/chat.pb.micro.go b/chat/proto/chat.pb.micro.go new file mode 100644 index 0000000..5b2fa6b --- /dev/null +++ b/chat/proto/chat.pb.micro.go @@ -0,0 +1,225 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: proto/chat.proto + +package chat + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +import ( + context "context" + api "github.com/micro/micro/v3/service/api" + client "github.com/micro/micro/v3/service/client" + server "github.com/micro/micro/v3/service/server" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// Reference imports to suppress errors if they are not otherwise used. +var _ api.Endpoint +var _ context.Context +var _ client.Option +var _ server.Option + +// Api Endpoints for Chat service + +func NewChatEndpoints() []*api.Endpoint { + return []*api.Endpoint{} +} + +// Client API for Chat service + +type ChatService interface { + // New creates a chat for a group of users. The RPC is idempotent so if it's called multiple times + // for the same users, the same response will be returned. It's good practice to design APIs as + // idempotent since this enables safe retries. + New(ctx context.Context, in *NewRequest, opts ...client.CallOption) (*NewResponse, error) + // History returns the historical messages in a chat + History(ctx context.Context, in *HistoryRequest, opts ...client.CallOption) (*HistoryResponse, error) + // Connect to a chat using a bidirectional stream enabling the client to send and recieve messages + // over a single RPC. When a message is sent on the stream, it will be added to the chat history + // and sent to the other connected users. When opening the connection, the client should provide + // the chat_id and user_id in the context so the server knows which messages to stream. + Connect(ctx context.Context, opts ...client.CallOption) (Chat_ConnectService, error) +} + +type chatService struct { + c client.Client + name string +} + +func NewChatService(name string, c client.Client) ChatService { + return &chatService{ + c: c, + name: name, + } +} + +func (c *chatService) New(ctx context.Context, in *NewRequest, opts ...client.CallOption) (*NewResponse, error) { + req := c.c.NewRequest(c.name, "Chat.New", in) + out := new(NewResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *chatService) History(ctx context.Context, in *HistoryRequest, opts ...client.CallOption) (*HistoryResponse, error) { + req := c.c.NewRequest(c.name, "Chat.History", in) + out := new(HistoryResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *chatService) Connect(ctx context.Context, opts ...client.CallOption) (Chat_ConnectService, error) { + req := c.c.NewRequest(c.name, "Chat.Connect", &Message{}) + stream, err := c.c.Stream(ctx, req, opts...) + if err != nil { + return nil, err + } + return &chatServiceConnect{stream}, nil +} + +type Chat_ConnectService interface { + Context() context.Context + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Send(*Message) error + Recv() (*Message, error) +} + +type chatServiceConnect struct { + stream client.Stream +} + +func (x *chatServiceConnect) Close() error { + return x.stream.Close() +} + +func (x *chatServiceConnect) Context() context.Context { + return x.stream.Context() +} + +func (x *chatServiceConnect) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *chatServiceConnect) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *chatServiceConnect) Send(m *Message) error { + return x.stream.Send(m) +} + +func (x *chatServiceConnect) Recv() (*Message, error) { + m := new(Message) + err := x.stream.Recv(m) + if err != nil { + return nil, err + } + return m, nil +} + +// Server API for Chat service + +type ChatHandler interface { + // New creates a chat for a group of users. The RPC is idempotent so if it's called multiple times + // for the same users, the same response will be returned. It's good practice to design APIs as + // idempotent since this enables safe retries. + New(context.Context, *NewRequest, *NewResponse) error + // History returns the historical messages in a chat + History(context.Context, *HistoryRequest, *HistoryResponse) error + // Connect to a chat using a bidirectional stream enabling the client to send and recieve messages + // over a single RPC. When a message is sent on the stream, it will be added to the chat history + // and sent to the other connected users. When opening the connection, the client should provide + // the chat_id and user_id in the context so the server knows which messages to stream. + Connect(context.Context, Chat_ConnectStream) error +} + +func RegisterChatHandler(s server.Server, hdlr ChatHandler, opts ...server.HandlerOption) error { + type chat interface { + New(ctx context.Context, in *NewRequest, out *NewResponse) error + History(ctx context.Context, in *HistoryRequest, out *HistoryResponse) error + Connect(ctx context.Context, stream server.Stream) error + } + type Chat struct { + chat + } + h := &chatHandler{hdlr} + return s.Handle(s.NewHandler(&Chat{h}, opts...)) +} + +type chatHandler struct { + ChatHandler +} + +func (h *chatHandler) New(ctx context.Context, in *NewRequest, out *NewResponse) error { + return h.ChatHandler.New(ctx, in, out) +} + +func (h *chatHandler) History(ctx context.Context, in *HistoryRequest, out *HistoryResponse) error { + return h.ChatHandler.History(ctx, in, out) +} + +func (h *chatHandler) Connect(ctx context.Context, stream server.Stream) error { + return h.ChatHandler.Connect(ctx, &chatConnectStream{stream}) +} + +type Chat_ConnectStream interface { + Context() context.Context + SendMsg(interface{}) error + RecvMsg(interface{}) error + Close() error + Send(*Message) error + Recv() (*Message, error) +} + +type chatConnectStream struct { + stream server.Stream +} + +func (x *chatConnectStream) Close() error { + return x.stream.Close() +} + +func (x *chatConnectStream) Context() context.Context { + return x.stream.Context() +} + +func (x *chatConnectStream) SendMsg(m interface{}) error { + return x.stream.Send(m) +} + +func (x *chatConnectStream) RecvMsg(m interface{}) error { + return x.stream.Recv(m) +} + +func (x *chatConnectStream) Send(m *Message) error { + return x.stream.Send(m) +} + +func (x *chatConnectStream) Recv() (*Message, error) { + m := new(Message) + if err := x.stream.Recv(m); err != nil { + return nil, err + } + return m, nil +} diff --git a/chat/proto/chat.proto b/chat/proto/chat.proto index 8670b78..ec8208c 100644 --- a/chat/proto/chat.proto +++ b/chat/proto/chat.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package chat; -option go_package = "github.com/micro/services/chat;chat"; +option go_package = "github.com/micro/services/chat/proto;chat"; service Chat { // New creates a chat for a group of users. The RPC is idempotent so if it's called multiple times diff --git a/go.mod b/go.mod index db81a78..75e32d3 100644 --- a/go.mod +++ b/go.mod @@ -17,14 +17,13 @@ require ( github.com/gosimple/slug v1.9.0 github.com/hashicorp/go-retryablehttp v0.6.7 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/micro/go-micro v1.18.0 // indirect - github.com/micro/go-micro/v3 v3.0.0-beta.3 + github.com/micro/go-micro v1.18.0 github.com/micro/go-plugins/broker/nats/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect github.com/micro/go-plugins/events/stream/nats/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect github.com/micro/go-plugins/metrics/prometheus/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect github.com/micro/go-plugins/registry/etcd/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect github.com/micro/go-plugins/store/cockroach/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect - github.com/micro/micro/v3 v3.0.0-beta.5.1 + github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015084013-5adee1bbfb5e github.com/miekg/dns v1.1.31 // indirect github.com/ulikunitz/xz v0.5.8 // indirect github.com/xanzy/go-gitlab v0.38.1 // indirect diff --git a/go.sum b/go.sum index 8efcd88..dfe720c 100644 --- a/go.sum +++ b/go.sum @@ -433,6 +433,9 @@ github.com/micro/micro/v3 v3.0.0-beta.4.0.20200918115538-32e9a17127d7 h1:Q9OvH5o github.com/micro/micro/v3 v3.0.0-beta.4.0.20200918115538-32e9a17127d7/go.mod h1:NeLvbrc7IpTU0EpRsJnEQyoH6Db3N3cVjt12mn4crmc= github.com/micro/micro/v3 v3.0.0-beta.5.1 h1:4v17JbrrLUN76SUKDgZoAXl9+cr5fSDHWeSnLZlqr7M= github.com/micro/micro/v3 v3.0.0-beta.5.1/go.mod h1:l4rOO3QkRJ7wCYZOlKh6n9ANRXs8OxN9H/9z4naUcqo= +github.com/micro/micro/v3 v3.0.0-beta.6 h1:TtklfOdte5Piu80clLpfb+4yK9jovt1s1svobChu/o0= +github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015084013-5adee1bbfb5e h1:VHBDhPnLcXqgCiYfjC8ip+r8UbV/9JekqZ6u8Kme4mc= +github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015084013-5adee1bbfb5e/go.mod h1:PK1Fa+RtdIVinOLBPgJQJP5Ov8V0ExXx+ywA80f9TdQ= github.com/micro/protoc-gen-micro v1.0.0/go.mod h1:C8ij4DJhapBmypcT00AXdb0cZ675/3PqUO02buWWqbE= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= From 9e1c0e990ff1b3e73e46ab06fa57218715f8b5b7 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Thu, 15 Oct 2020 15:05:17 +0100 Subject: [PATCH 3/6] Add chat client --- chat/client/main.go | 121 ++++++++++++++++++++ chat/handler/handler.go | 51 ++++++--- chat/proto/chat.pb.go | 64 +++++------ chat/proto/chat.pb.micro.go | 2 +- chat/proto/chat.proto | 2 +- go.mod | 24 +--- go.sum | 222 +++--------------------------------- 7 files changed, 209 insertions(+), 277 deletions(-) create mode 100644 chat/client/main.go diff --git a/chat/client/main.go b/chat/client/main.go new file mode 100644 index 0000000..9091b34 --- /dev/null +++ b/chat/client/main.go @@ -0,0 +1,121 @@ +// Package main is a client for the chat service to demonstrate how it would work for a client. To +// run the client, first launch the chat service by running `micro run ./chat` from the top level of +// this repo. Then run `micro run ./chat/client` and `micro logs -f client` to follow the logs of +// the client. +package main + +import ( + "context" + "fmt" + "time" + + "github.com/google/uuid" + "github.com/micro/micro/v3/service" + "github.com/micro/micro/v3/service/context/metadata" + "github.com/micro/micro/v3/service/logger" + chat "github.com/micro/services/chat/proto" +) + +var ( + userOneID = "user-one-" + uuid.New().String() + userTwoID = "user-two-" + uuid.New().String() +) + +func main() { + // create a chat service client + srv := service.New() + cli := chat.NewChatService("chat", srv.Client()) + + // create a chat for our users + userIDs := []string{userOneID, userTwoID} + nRsp, err := cli.New(context.TODO(), &chat.NewRequest{UserIds: userIDs}) + if err != nil { + logger.Fatalf("Error creating the chat: %v", err) + } + chatID := nRsp.GetChatId() + logger.Infof("Chat Created. ID: %v", chatID) + + // list the number messages in the chat history + hRsp, err := cli.History(context.TODO(), &chat.HistoryRequest{ChatId: chatID}) + if err != nil { + logger.Fatalf("Error getting the chat history: %v", err) + } + logger.Infof("Chat has %v message(s)", len(hRsp.Messages)) + + // create a channel to handle errors + errChan := make(chan error) + + // run user one + go func() { + ctx := metadata.NewContext(context.TODO(), metadata.Metadata{ + "user-id": userOneID, "chat-id": chatID, + }) + stream, err := cli.Connect(ctx) + if err != nil { + errChan <- err + return + } + + for i := 1; true; i++ { + // send a message to the chat + err = stream.Send(&chat.Message{ + ClientId: uuid.New().String(), + SentAt: time.Now().Unix(), + Subject: "Message from user one", + Text: fmt.Sprintf("Message #%v", i), + }) + if err != nil { + errChan <- err + return + } + logger.Infof("User one sent message") + + // wait for user two to respond + msg, err := stream.Recv() + if err != nil { + errChan <- err + return + } + logger.Infof("User one recieved message %v from %v", msg.Text, msg.UserId) + time.Sleep(time.Second) + } + }() + + // run user two + go func() { + ctx := metadata.NewContext(context.TODO(), metadata.Metadata{ + "user-id": userTwoID, "chat-id": chatID, + }) + stream, err := cli.Connect(ctx) + if err != nil { + errChan <- err + return + } + + for i := 1; true; i++ { + // send a response to the chat + err = stream.Send(&chat.Message{ + ClientId: uuid.New().String(), + SentAt: time.Now().Unix(), + Subject: "Response from user two", + Text: fmt.Sprintf("Response #%v", i), + }) + if err != nil { + errChan <- err + return + } + logger.Infof("User two sent message") + + // wait for a message from user one + msg, err := stream.Recv() + if err != nil { + errChan <- err + return + } + logger.Infof("User two recieved message %v from %v", msg.Text, msg.UserId) + time.Sleep(time.Second) + } + }() + + logger.Fatal(<-errChan) +} diff --git a/chat/handler/handler.go b/chat/handler/handler.go index b6e2527..da83307 100644 --- a/chat/handler/handler.go +++ b/chat/handler/handler.go @@ -7,12 +7,13 @@ import ( "github.com/micro/micro/v3/service/context/metadata" - // import the proto, it's standard to import the services own proto under the alias pb "github.com/google/uuid" "github.com/micro/micro/v3/service/errors" "github.com/micro/micro/v3/service/events" "github.com/micro/micro/v3/service/logger" "github.com/micro/micro/v3/service/store" + + // it's standard to import the services own proto under the alias pb pb "github.com/micro/services/chat/proto" ) @@ -22,8 +23,9 @@ func New() pb.ChatHandler { } const ( - storeKeyPrefix = "chat/" - eventKeyPrefix = "chat/" + chatStoreKeyPrefix = "chats/" + chatEventKeyPrefix = "chats/" + messageStoreKeyPrefix = "messages/" ) // handler satisfies the ChatHandler interface. You can see this inteface defined in chat.pb.micro.go @@ -58,11 +60,11 @@ func (h *handler) New(ctx context.Context, req *pb.NewRequest, rsp *pb.NewRespon sort.Strings(sortedIDs) // key to lookup the chat in the store using, e.g. "chat/usera-userb-userc" - key := storeKeyPrefix + strings.Join(sortedIDs, "-") + key := chatStoreKeyPrefix + strings.Join(sortedIDs, "-") // read from the store to check if a chat with these users already exists recs, err := store.Read(key) - if err != nil { + if err == nil { // if an error wasn't returned, at least one record was found. The value returned by the store // is the bytes representation of the chat id. We'll convert this back into a string and return // it to the client. @@ -80,9 +82,9 @@ func (h *handler) New(ctx context.Context, req *pb.NewRequest, rsp *pb.NewRespon // no chat id was returned so we'll generate one, write it to the store and then return it to the // client chatID := uuid.New().String() - record := store.Record{Key: key, Value: []byte(chatID)} + record := store.Record{Key: chatStoreKeyPrefix + chatID, Value: []byte(chatID)} if err := store.Write(&record); err != nil { - logger.Errorf("Error writing to the store. Key: %v. Error: %v", key, err) + logger.Errorf("Error writing to the store. Key: %v. Error: %v", record.Key, err) return errors.InternalServerError("chat.New.Unknown", "Error writing to the store") } @@ -104,7 +106,7 @@ func (h *handler) History(ctx context.Context, req *pb.HistoryRequest, rsp *pb.H } // lookup the chat from the store to ensure it's valid - if _, err := store.Read(storeKeyPrefix + req.ChatId); err == store.ErrNotFound { + if _, err := store.Read(chatStoreKeyPrefix + req.ChatId); err == store.ErrNotFound { return errors.BadRequest("chat.History.InvalidChatID", "Chat not found with this ID") } else if err != nil { logger.Errorf("Error reading from the store. Chat ID: %v. Error: %v", req.ChatId, err) @@ -114,7 +116,7 @@ func (h *handler) History(ctx context.Context, req *pb.HistoryRequest, rsp *pb.H // lookup the historical messages for the chat using the event store. lots of packages in micro // support options, in this case we'll pass the ReadLimit option to restrict the number of messages // we'll load from the events store. - messages, err := events.Read(eventKeyPrefix+req.ChatId, events.ReadLimit(50)) + messages, err := events.Read(chatEventKeyPrefix+req.ChatId, events.ReadLimit(50)) if err != nil { logger.Errorf("Error reading from the event store. Chat ID: %v. Error: %v", req.ChatId, err) return errors.InternalServerError("chat.History.Unknown", "Error reading from the event store") @@ -143,17 +145,17 @@ func (h *handler) History(ctx context.Context, req *pb.HistoryRequest, rsp *pb.H func (h *handler) Connect(ctx context.Context, stream pb.Chat_ConnectStream) error { // the client passed the chat id and user id in the request context. we'll load that information // now and validate it. If any information is missing we'll return a BadRequest error to the client - userID, ok := metadata.Get(ctx, "UserID") + userID, ok := metadata.Get(ctx, "user-id") if !ok { return errors.BadRequest("chat.Connect.MissingUserID", "UserID missing in context") } - chatID, ok := metadata.Get(ctx, "ChatID") + chatID, ok := metadata.Get(ctx, "chat-id") if !ok { return errors.BadRequest("chat.Connect.MissingChatID", "ChatId missing in context") } // lookup the chat from the store to ensure it's valid - if _, err := store.Read(storeKeyPrefix + chatID); err == store.ErrNotFound { + if _, err := store.Read(chatStoreKeyPrefix + chatID); err == store.ErrNotFound { return errors.BadRequest("chat.Connect.InvalidChatID", "Chat not found with this ID") } else if err != nil { logger.Errorf("Error reading from the store. Chat ID: %v. Error: %v", chatID, err) @@ -175,9 +177,8 @@ func (h *handler) Connect(ctx context.Context, stream pb.Chat_ConnectStream) err // create an event stream to consume messages posted by other users into the chat. we'll use the // user id as a queue to ensure each user recieves the message - evStream, err := events.Subscribe(eventKeyPrefix+chatID, events.WithQueue(userID)) + evStream, err := events.Subscribe(chatEventKeyPrefix+chatID, events.WithQueue(userID)) if err != nil { - defer cancel() logger.Errorf("Error streaming events. Chat ID: %v. Error: %v", chatID, err) return errors.InternalServerError("chat.Connect.Unknown", "Error connecting to the event stream") } @@ -235,8 +236,26 @@ func (h *handler) Connect(ctx context.Context, stream pb.Chat_ConnectStream) err // an error occured in another goroutine, terminate the stream return err case msg := <-msgChan: - // a message was recieved from the client, send it to the event stream - if err := events.Publish(eventKeyPrefix+chatID, msg); err != nil { + // a message was recieved from the client. validate it hasn't been recieved before + if _, err := store.Read(messageStoreKeyPrefix + msg.ClientId); err == nil { + // the message has already been processed + continue + } else if err != store.ErrNotFound { + // an unexpected error occured + return err + } + + // set the defaults + msg.UserId = userID + msg.ChatId = chatID + + // send the message to the event stream + if err := events.Publish(chatEventKeyPrefix+chatID, msg); err != nil { + return err + } + + // record the messages client id + if err := store.Write(&store.Record{Key: messageStoreKeyPrefix + msg.ClientId}); err != nil { return err } } diff --git a/chat/proto/chat.pb.go b/chat/proto/chat.pb.go index e67ba30..8806d76 100644 --- a/chat/proto/chat.pb.go +++ b/chat/proto/chat.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: proto/chat.proto +// source: chat/proto/chat.proto package chat @@ -32,7 +32,7 @@ func (m *NewRequest) Reset() { *m = NewRequest{} } func (m *NewRequest) String() string { return proto.CompactTextString(m) } func (*NewRequest) ProtoMessage() {} func (*NewRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_ed7e7dde45555b7d, []int{0} + return fileDescriptor_825b1469f80f958d, []int{0} } func (m *NewRequest) XXX_Unmarshal(b []byte) error { @@ -72,7 +72,7 @@ func (m *NewResponse) Reset() { *m = NewResponse{} } func (m *NewResponse) String() string { return proto.CompactTextString(m) } func (*NewResponse) ProtoMessage() {} func (*NewResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_ed7e7dde45555b7d, []int{1} + return fileDescriptor_825b1469f80f958d, []int{1} } func (m *NewResponse) XXX_Unmarshal(b []byte) error { @@ -114,7 +114,7 @@ func (m *HistoryRequest) Reset() { *m = HistoryRequest{} } func (m *HistoryRequest) String() string { return proto.CompactTextString(m) } func (*HistoryRequest) ProtoMessage() {} func (*HistoryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_ed7e7dde45555b7d, []int{2} + return fileDescriptor_825b1469f80f958d, []int{2} } func (m *HistoryRequest) XXX_Unmarshal(b []byte) error { @@ -154,7 +154,7 @@ func (m *HistoryResponse) Reset() { *m = HistoryResponse{} } func (m *HistoryResponse) String() string { return proto.CompactTextString(m) } func (*HistoryResponse) ProtoMessage() {} func (*HistoryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_ed7e7dde45555b7d, []int{3} + return fileDescriptor_825b1469f80f958d, []int{3} } func (m *HistoryResponse) XXX_Unmarshal(b []byte) error { @@ -193,7 +193,7 @@ type Message struct { // id of the user who sent the message UserId string `protobuf:"bytes,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // time time the message was sent in unix format - SentAt int32 `protobuf:"varint,5,opt,name=sent_at,json=sentAt,proto3" json:"sent_at,omitempty"` + SentAt int64 `protobuf:"varint,5,opt,name=sent_at,json=sentAt,proto3" json:"sent_at,omitempty"` // subject of the message Subject string `protobuf:"bytes,6,opt,name=subject,proto3" json:"subject,omitempty"` // text of the message @@ -207,7 +207,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_ed7e7dde45555b7d, []int{4} + return fileDescriptor_825b1469f80f958d, []int{4} } func (m *Message) XXX_Unmarshal(b []byte) error { @@ -256,7 +256,7 @@ func (m *Message) GetUserId() string { return "" } -func (m *Message) GetSentAt() int32 { +func (m *Message) GetSentAt() int64 { if m != nil { return m.SentAt } @@ -285,30 +285,30 @@ func init() { proto.RegisterType((*Message)(nil), "chat.Message") } -func init() { proto.RegisterFile("proto/chat.proto", fileDescriptor_ed7e7dde45555b7d) } +func init() { proto.RegisterFile("chat/proto/chat.proto", fileDescriptor_825b1469f80f958d) } -var fileDescriptor_ed7e7dde45555b7d = []byte{ +var fileDescriptor_825b1469f80f958d = []byte{ // 351 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0x41, 0x4f, 0xf2, 0x40, - 0x10, 0xcd, 0x42, 0x69, 0x61, 0xc8, 0xc7, 0x87, 0x1b, 0x8d, 0x2b, 0x5e, 0x48, 0x0f, 0x5a, 0x24, - 0xa1, 0x06, 0x13, 0x2f, 0x7a, 0x51, 0x2e, 0x72, 0x90, 0x43, 0x8f, 0x5e, 0x48, 0x69, 0x37, 0xb0, - 0x46, 0xba, 0xd8, 0xd9, 0x8a, 0xfe, 0x12, 0x7f, 0x86, 0x7f, 0xd1, 0xec, 0x6e, 0x41, 0x30, 0xf1, - 0x36, 0xef, 0xbd, 0x99, 0xd9, 0x37, 0x2f, 0x0b, 0xed, 0x55, 0x2e, 0x95, 0x0c, 0x93, 0x45, 0xac, - 0x06, 0xa6, 0xa4, 0x8e, 0xae, 0xfd, 0x73, 0x80, 0x09, 0x5f, 0x47, 0xfc, 0xb5, 0xe0, 0xa8, 0xe8, - 0x09, 0xd4, 0x0b, 0xe4, 0xf9, 0x54, 0xa4, 0xc8, 0x48, 0xb7, 0x1a, 0x34, 0x22, 0x4f, 0xe3, 0x71, - 0x8a, 0xfe, 0x19, 0x34, 0x4d, 0x23, 0xae, 0x64, 0x86, 0x9c, 0x1e, 0x83, 0xa7, 0xe7, 0xa7, 0x22, - 0x65, 0xa4, 0x4b, 0x82, 0x46, 0xe4, 0x6a, 0x38, 0x4e, 0xfd, 0x1e, 0xb4, 0x1e, 0x04, 0x2a, 0x99, - 0x7f, 0x6c, 0x96, 0xfe, 0xd9, 0x7a, 0x0b, 0xff, 0xb7, 0xad, 0xe5, 0xda, 0x1e, 0xd4, 0x97, 0x1c, - 0x31, 0x9e, 0x73, 0x6b, 0xa0, 0x39, 0xfc, 0x37, 0x30, 0x9e, 0x1f, 0x2d, 0x1b, 0x6d, 0x65, 0xff, - 0x8b, 0x80, 0x57, 0xb2, 0xb4, 0x05, 0x95, 0xed, 0xf6, 0x8a, 0x48, 0xe9, 0x29, 0x34, 0x92, 0x17, - 0xc1, 0x33, 0xf3, 0x68, 0xc5, 0xd0, 0x75, 0x4b, 0x8c, 0xd3, 0x5d, 0x3f, 0xd5, 0x5d, 0x3f, 0x5a, - 0x28, 0xaf, 0x67, 0x8e, 0x15, 0xec, 0xf1, 0x5a, 0x40, 0xbd, 0x2c, 0x56, 0xac, 0xd6, 0x25, 0x41, - 0x2d, 0x72, 0x35, 0xbc, 0x53, 0x94, 0x81, 0x87, 0xc5, 0xec, 0x99, 0x27, 0x8a, 0xb9, 0x66, 0x62, - 0x03, 0x29, 0x05, 0x47, 0xf1, 0x77, 0xc5, 0x3c, 0x43, 0x9b, 0x7a, 0xf8, 0x49, 0xc0, 0x19, 0x2d, - 0x62, 0x45, 0x2f, 0xa0, 0x3a, 0xe1, 0x6b, 0xda, 0xb6, 0xa7, 0xfd, 0xe4, 0xdf, 0x39, 0xd8, 0x61, - 0xca, 0x44, 0xae, 0xc1, 0x2b, 0x43, 0xa2, 0x87, 0x56, 0xdd, 0x8f, 0xb7, 0x73, 0xf4, 0x8b, 0x2d, - 0xe7, 0xfa, 0xe0, 0x8d, 0x64, 0x96, 0x69, 0x2f, 0xfb, 0x11, 0x76, 0xf6, 0x61, 0x40, 0x2e, 0xc9, - 0x7d, 0xff, 0xa9, 0x37, 0x17, 0x6a, 0x51, 0xcc, 0x06, 0x89, 0x5c, 0x86, 0x4b, 0x91, 0xe4, 0x32, - 0x44, 0x9e, 0xbf, 0x89, 0x84, 0xa3, 0xf9, 0x33, 0xa1, 0xf9, 0x33, 0x37, 0xba, 0x9c, 0xb9, 0xa6, - 0xbe, 0xfa, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x71, 0x1b, 0x44, 0xc0, 0x53, 0x02, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xcd, 0x4e, 0xf2, 0x40, + 0x14, 0xcd, 0xd0, 0x7e, 0x1d, 0xb8, 0xe4, 0x43, 0x9d, 0x48, 0x1c, 0x71, 0x43, 0xba, 0xd0, 0x22, + 0x09, 0x35, 0x98, 0xb8, 0xd1, 0x8d, 0xb2, 0x91, 0x85, 0x2c, 0xba, 0x74, 0x43, 0x4a, 0x3b, 0x81, + 0x31, 0xd2, 0xc1, 0xce, 0x54, 0xf4, 0x49, 0x7c, 0x0c, 0x5f, 0xd1, 0xcc, 0x4c, 0xf9, 0xa9, 0x89, + 0xbb, 0xf3, 0x33, 0xf7, 0xf6, 0xdc, 0x93, 0x42, 0x3b, 0x59, 0xc4, 0x2a, 0x5c, 0xe5, 0x42, 0x89, + 0x50, 0xc3, 0x81, 0x81, 0xc4, 0xd5, 0xd8, 0xbf, 0x00, 0x98, 0xb0, 0x75, 0xc4, 0xde, 0x0a, 0x26, + 0x15, 0x39, 0x85, 0x7a, 0x21, 0x59, 0x3e, 0xe5, 0xa9, 0xa4, 0xa8, 0xeb, 0x04, 0x8d, 0x08, 0x6b, + 0x3e, 0x4e, 0xa5, 0x7f, 0x0e, 0x4d, 0xf3, 0x50, 0xae, 0x44, 0x26, 0x19, 0x39, 0x01, 0xac, 0xe7, + 0xa7, 0x3c, 0xa5, 0xa8, 0x8b, 0x82, 0x46, 0xe4, 0x69, 0x3a, 0x4e, 0xfd, 0x1e, 0xb4, 0x1e, 0xb9, + 0x54, 0x22, 0xff, 0xdc, 0x2c, 0xfd, 0xf3, 0xe9, 0x1d, 0x1c, 0x6c, 0x9f, 0x96, 0x6b, 0x7b, 0x50, + 0x5f, 0x32, 0x29, 0xe3, 0x39, 0xb3, 0x01, 0x9a, 0xc3, 0xff, 0x03, 0x93, 0xf9, 0xc9, 0xaa, 0xd1, + 0xd6, 0xf6, 0xbf, 0x11, 0xe0, 0x52, 0x25, 0x2d, 0xa8, 0x6d, 0xb7, 0xd7, 0x78, 0x4a, 0xce, 0xa0, + 0x91, 0xbc, 0x72, 0x96, 0x99, 0x8f, 0xd6, 0x8c, 0x5c, 0xb7, 0xc2, 0x38, 0xdd, 0xcf, 0xe3, 0xec, + 0xe7, 0xd1, 0x46, 0x79, 0x3d, 0x75, 0xad, 0x61, 0x8f, 0xd7, 0x86, 0xd4, 0xcb, 0x62, 0x45, 0xff, + 0x75, 0x51, 0xe0, 0x44, 0x9e, 0xa6, 0xf7, 0x8a, 0x50, 0xc0, 0xb2, 0x98, 0xbd, 0xb0, 0x44, 0x51, + 0xcf, 0x4c, 0x6c, 0x28, 0x21, 0xe0, 0x2a, 0xf6, 0xa1, 0x28, 0x36, 0xb2, 0xc1, 0xc3, 0x2f, 0x04, + 0xee, 0x68, 0x11, 0x2b, 0x72, 0x09, 0xce, 0x84, 0xad, 0xc9, 0xa1, 0x3d, 0x6d, 0xd7, 0x7f, 0xe7, + 0x68, 0x4f, 0x29, 0x1b, 0xb9, 0x01, 0x5c, 0x96, 0x44, 0x8e, 0xad, 0x5b, 0xad, 0xb7, 0xd3, 0xfe, + 0xa5, 0x96, 0x73, 0x7d, 0xc0, 0x23, 0x91, 0x65, 0x3a, 0x4b, 0xb5, 0xc2, 0x4e, 0x95, 0x06, 0xe8, + 0x0a, 0x3d, 0xf4, 0x9f, 0x7b, 0x73, 0xae, 0x16, 0xc5, 0x6c, 0x90, 0x88, 0x65, 0xb8, 0xe4, 0x49, + 0x2e, 0x42, 0xc9, 0xf2, 0x77, 0x9e, 0x30, 0x19, 0xee, 0x7e, 0x9f, 0x5b, 0x0d, 0x67, 0x9e, 0xc1, + 0xd7, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x53, 0xab, 0xf2, 0x77, 0x58, 0x02, 0x00, 0x00, } diff --git a/chat/proto/chat.pb.micro.go b/chat/proto/chat.pb.micro.go index 5b2fa6b..482e3e3 100644 --- a/chat/proto/chat.pb.micro.go +++ b/chat/proto/chat.pb.micro.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-micro. DO NOT EDIT. -// source: proto/chat.proto +// source: chat/proto/chat.proto package chat diff --git a/chat/proto/chat.proto b/chat/proto/chat.proto index ec8208c..981488a 100644 --- a/chat/proto/chat.proto +++ b/chat/proto/chat.proto @@ -50,7 +50,7 @@ message Message { // id of the user who sent the message string user_id = 4; // time time the message was sent in unix format - int32 sent_at = 5; + int64 sent_at = 5; // subject of the message string subject = 6; // text of the message diff --git a/go.mod b/go.mod index 75e32d3..5e8809c 100644 --- a/go.mod +++ b/go.mod @@ -3,32 +3,13 @@ module github.com/micro/services go 1.14 require ( - github.com/caddyserver/certmagic v0.12.0 // indirect - github.com/cenkalti/backoff/v4 v4.0.2 // indirect - github.com/cloudflare/cloudflare-go v0.13.3 // indirect - github.com/evanphx/json-patch/v5 v5.1.0 // indirect - github.com/go-acme/lego/v3 v3.9.0 // indirect - github.com/gobwas/httphead v0.0.0-20200921212729-da3d93bc3c58 // indirect - github.com/gobwas/ws v1.0.4 // indirect github.com/golang/protobuf v1.4.2 github.com/google/uuid v1.1.2 - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/mux v1.8.0 // indirect github.com/gosimple/slug v1.9.0 - github.com/hashicorp/go-retryablehttp v0.6.7 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/micro/go-micro v1.18.0 - github.com/micro/go-plugins/broker/nats/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect - github.com/micro/go-plugins/events/stream/nats/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect - github.com/micro/go-plugins/metrics/prometheus/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect - github.com/micro/go-plugins/registry/etcd/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect - github.com/micro/go-plugins/store/cockroach/v3 v3.0.0-20200908121001-4ea6f6760baf // indirect - github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015084013-5adee1bbfb5e + github.com/micro/go-micro/v3 v3.0.0-beta.2 + github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015134940-68ac1ddfa568 github.com/miekg/dns v1.1.31 // indirect github.com/ulikunitz/xz v0.5.8 // indirect - github.com/xanzy/go-gitlab v0.38.1 // indirect - github.com/xlab/treeprint v1.0.0 // indirect - go.uber.org/multierr v1.6.0 // indirect golang.org/x/crypto v0.0.0-20201002094018-c90954cbb977 // indirect golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 // indirect golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect @@ -36,7 +17,6 @@ require ( google.golang.org/genproto v0.0.0-20201001141541-efaab9d3c4f7 // indirect google.golang.org/grpc v1.32.0 google.golang.org/protobuf v1.25.0 - gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect ) diff --git a/go.sum b/go.sum index dfe720c..bdda92b 100644 --- a/go.sum +++ b/go.sum @@ -49,32 +49,22 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c/go.mod h1:7xhjOwRV2+0HXGmM0jxaEu+ZiXJFoVZOTfL/dmqbrD8= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= -github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.18/go.mod h1:L+HB2uBoDgi3+r1pJEJcbGwyyHhd2QXaGsKLbDwtm8Q= -github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= -github.com/aliyun/alibaba-cloud-sdk-go v1.61.112/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.30.20/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= -github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -86,23 +76,14 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= -github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= -github.com/bwmarrin/discordgo v0.20.1/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/caddyserver/certmagic v0.10.6 h1:sCya6FmfaN74oZE46kqfaFOVoROD/mF36rTQfjN7TZc= github.com/caddyserver/certmagic v0.10.6/go.mod h1:Y8jcUBctgk/IhpAzlHKfimZNyXCkfGgRTC0orl8gROQ= -github.com/caddyserver/certmagic v0.12.0 h1:1f7kxykaJkOVVpXJ8ZrC6RAO5F6+kKm9U7dBFbLNeug= -github.com/caddyserver/certmagic v0.12.0/go.mod h1:tr26xh+9fY5dN0J6IPAlMj07qpog22PJKa7Nw7j835U= -github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6RFYAU= github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= -github.com/cenkalti/backoff/v4 v4.0.2 h1:JIufpQLbh4DkbQoii76ItQIUFzevQSqOLZca4eamEDs= -github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -112,45 +93,38 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= github.com/cloudflare/cloudflare-go v0.10.9 h1:d8KOgLpYiC+Xq3T4tuO+/goM+RZvuO+T4pojuv8giL8= github.com/cloudflare/cloudflare-go v0.10.9/go.mod h1:5TrsWH+3f4NV6WjtS5QFp+DifH81rph40gU374Sh0dQ= -github.com/cloudflare/cloudflare-go v0.13.3 h1:smLtF9b56YxIgv+kFq4ELH8ZP9CXNtJr0zDy8UKvfT8= -github.com/cloudflare/cloudflare-go v0.13.3/go.mod h1:9KcluT/RE6fGjr/YFWDAfZrOYkCvRIFRUFiaKQAbFIE= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.18+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.25+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= -github.com/cpu/goacmedns v0.0.2/go.mod h1:4MipLkI+qScwqtVxcNO6okBhbgRrr7/tKXUSgSL0teQ= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= -github.com/dnsimple/dnsimple-go v0.60.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -160,31 +134,19 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/ef-ds/deque v1.0.4-0.20190904040645-54cb57c252a1/go.mod h1:HvODWzv6Y6kBf3Ah2WzN1bHjDUezGLaAhwuWVwfpEJs= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch/v5 v5.0.0 h1:dKTrUeykyQwKb/kx7Z+4ukDs6l+4L41HqG1XHnhX7WE= github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/evanphx/json-patch/v5 v5.1.0 h1:B0aXl1o/1cP8NbviYiBMkcHBtUjIJ1/Ccg6b+SwCLQg= -github.com/evanphx/json-patch/v5 v5.1.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c/go.mod h1:pFdJbAhRf7rh6YYMUdIQGyzne6zYL1tCUW8QV2B3UfY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= github.com/fsouza/go-dockerclient v1.6.0/go.mod h1:YWwtNPuL4XTX1SKJQk86cWPmmqwx+4np9qfPbb+znGc= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= github.com/go-acme/lego/v3 v3.4.0 h1:deB9NkelA+TfjGHVw8J7iKl/rMtffcGMWSMmptvMv0A= github.com/go-acme/lego/v3 v3.4.0/go.mod h1:xYbLDuxq3Hy4bMUT1t9JIuz6GWIWb3m5X+TeTHYaT7M= -github.com/go-acme/lego/v3 v3.9.0 h1:Kyvg2GGqRJHfK2Stu57M45TDTx0y1bsxLH7lpeP3n0A= -github.com/go-acme/lego/v3 v3.9.0/go.mod h1:va0cvQpxpJ3u2OA534L8TDn+lsr2oujLzPckLOLnUGQ= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -193,37 +155,28 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/httphead v0.0.0-20200921212729-da3d93bc3c58 h1:YyrUZvJaU8Q0QsoVo+xLFBgWDTam29PKea6GYmwvSiQ= -github.com/gobwas/httphead v0.0.0-20200921212729-da3d93bc3c58/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.3 h1:ZOigqf7iBxkA4jdQ3am7ATzdlOFp9YzA6NmuvEEZc9g= github.com/gobwas/ws v1.0.3/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.0.4 h1:5eXU1CZhpQdq5kXbKb+sECH5Ia5KiO6CYzIzdlVx6Bs= -github.com/gobwas/ws v1.0.4/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -234,7 +187,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= @@ -281,22 +233,13 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= -github.com/gophercloud/gophercloud v0.6.1-0.20191122030953-d8ac278c1c9d/go.mod h1:ozGNgr9KYOVATV5jsgHl/ceCDXGuguqOZAzoQ/2vcNM= -github.com/gophercloud/gophercloud v0.7.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss= -github.com/gophercloud/utils v0.0.0-20200508015959-b0167b94122c/go.mod h1:ehWUbLQJPqS0Ep+CxeD559hsm9pthPXadJNKwZkp43w= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs= github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg= @@ -318,11 +261,7 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1: github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.4 h1:BbgctKO892xEyOXnGiaAwIoSq1QZ/SS4AhjoAh9DnfY= github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= -github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -335,21 +274,16 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= -github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8= github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/joncalhoun/qson v0.0.0-20170526102502-8a9cab3a62b1/go.mod h1:DFXrEwSRX0p/aSvxE21319menCBFeQO0jXpRj7LEZUA= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= @@ -357,17 +291,13 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuyPzG0/vVbWwMwLJ+P6yJI5FN8= github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.2.5/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= -github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -375,74 +305,29 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libdns/libdns v0.1.0 h1:0ctCOrVJsVzj53mop1angHp/pE3hmAhP7KiHvR0HD04= -github.com/libdns/libdns v0.1.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= -github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= -github.com/lucas-clemente/quic-go v0.13.1/go.mod h1:Vn3/Fb0/77b02SGhQk36KzOUmXgVpFfizUfW5WMaqyU= -github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE= -github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= -github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= -github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mholt/acmez v0.1.1 h1:KQODCqk+hBn3O7qfCRPj6L96uG65T5BSS95FKNEqtdA= -github.com/mholt/acmez v0.1.1/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM= -github.com/mholt/certmagic v0.7.5/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= -github.com/mholt/certmagic v0.8.3/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= -github.com/micro/cli v0.2.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= -github.com/micro/go-micro v1.16.0/go.mod h1:A0F58bHLh2m0LAI9QyhvmbN8c1cxhAZo3cM6s+iDsrM= -github.com/micro/go-micro v1.18.0 h1:gP70EZVHpJuUIT0YWth192JmlIci+qMOEByHm83XE9E= -github.com/micro/go-micro v1.18.0/go.mod h1:klwUJL1gkdY1MHFyz+fFJXn52dKcty4hoe95Mp571AA= +github.com/micro/go-micro/v3 v3.0.0-beta.2 h1:LYaTCdw0T8So1EC74F/5c/8oBGT2L25ogTlk0NGo4CA= github.com/micro/go-micro/v3 v3.0.0-beta.2/go.mod h1:8VQzHPkol6RwDYO4vhxJk3irqb2XDz/mM8S6j7QNXjQ= -github.com/micro/go-micro/v3 v3.0.0-beta.2.0.20200911124113-3bb76868d194/go.mod h1:dx3ZCcO8zr6Za0Ri05Jk0F7APdTgj15wGBHje9+S++c= -github.com/micro/go-micro/v3 v3.0.0-beta.2.0.20200918112555-9168c7c61064 h1:H3TSt+2Z/FAv4xy8UwhuqF8iYOg0GX57bDwPB6AXxIg= -github.com/micro/go-micro/v3 v3.0.0-beta.2.0.20200918112555-9168c7c61064/go.mod h1:uOClwKuoS4hmK6LdY6azBEqDVh8EKx0r9pSenum3z48= -github.com/micro/go-micro/v3 v3.0.0-beta.2.0.20200929133051-87e898f4fc62 h1:yFK8GK2Lt43YHgF7k7q8NNsgz+0vfTOdv0R/YPafFWQ= -github.com/micro/go-micro/v3 v3.0.0-beta.2.0.20200929133051-87e898f4fc62/go.mod h1:DiwYchJ8kCWOZVXMsZwuFcNDAdSCS6aEbYfEni4LvK4= -github.com/micro/go-micro/v3 v3.0.0-beta.3 h1:4B8UbMg+HRL3Cb7Ly1tIY6c9t0dNjNwEf0Tyh+Jk4zk= -github.com/micro/go-micro/v3 v3.0.0-beta.3/go.mod h1:DiwYchJ8kCWOZVXMsZwuFcNDAdSCS6aEbYfEni4LvK4= -github.com/micro/go-plugins/broker/nats/v3 v3.0.0-20200908121001-4ea6f6760baf/go.mod h1:tO2vsiYt8UmWhgFxhEAhzjyf8kYLLujuqaMcJguywbU= -github.com/micro/go-plugins/events/stream/nats/v3 v3.0.0-20200908121001-4ea6f6760baf/go.mod h1:Cq7p9FXF50cW6fvGHqyP60pQRHhkLdzPQXnj8GoHDds= -github.com/micro/go-plugins/metrics/prometheus/v3 v3.0.0-20200908121001-4ea6f6760baf/go.mod h1:gIRIjMSjfvovtBizygGGKq1hzoLkgB+ipo6Yk8qyTvI= -github.com/micro/go-plugins/registry/etcd/v3 v3.0.0-20200908121001-4ea6f6760baf/go.mod h1:m1oOc/fLZH+uFri7u5c+6bVQ10bd5nB5MFjE47Z9l0w= -github.com/micro/go-plugins/store/cockroach/v3 v3.0.0-20200908121001-4ea6f6760baf/go.mod h1:PU7joUtgK+z+sAAjz/TPdM8xHQPTlfLSOPoBuG8oKuk= -github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= -github.com/micro/micro v1.18.0 h1:v+xiQOXbT9xxotLwu1nJM81t4FbruBxZSSyIdhUfujM= -github.com/micro/micro/v3 v3.0.0-beta.4.0.20200918115538-32e9a17127d7 h1:Q9OvH5oZGu9XsmZlUCG5GtSelM4YiRMpv0aD4nA5lZs= -github.com/micro/micro/v3 v3.0.0-beta.4.0.20200918115538-32e9a17127d7/go.mod h1:NeLvbrc7IpTU0EpRsJnEQyoH6Db3N3cVjt12mn4crmc= -github.com/micro/micro/v3 v3.0.0-beta.5.1 h1:4v17JbrrLUN76SUKDgZoAXl9+cr5fSDHWeSnLZlqr7M= -github.com/micro/micro/v3 v3.0.0-beta.5.1/go.mod h1:l4rOO3QkRJ7wCYZOlKh6n9ANRXs8OxN9H/9z4naUcqo= -github.com/micro/micro/v3 v3.0.0-beta.6 h1:TtklfOdte5Piu80clLpfb+4yK9jovt1s1svobChu/o0= -github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015084013-5adee1bbfb5e h1:VHBDhPnLcXqgCiYfjC8ip+r8UbV/9JekqZ6u8Kme4mc= -github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015084013-5adee1bbfb5e/go.mod h1:PK1Fa+RtdIVinOLBPgJQJP5Ov8V0ExXx+ywA80f9TdQ= -github.com/micro/protoc-gen-micro v1.0.0/go.mod h1:C8ij4DJhapBmypcT00AXdb0cZ675/3PqUO02buWWqbE= -github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015134940-68ac1ddfa568 h1:Nz+CWXbuowAMG8GBJYufNCaWoNW0WqN0IohFAdlMGdY= +github.com/micro/micro/v3 v3.0.0-beta.6.0.20201015134940-68ac1ddfa568/go.mod h1:PK1Fa+RtdIVinOLBPgJQJP5Ov8V0ExXx+ywA80f9TdQ= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM= github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.30/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo= github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= @@ -450,40 +335,36 @@ github.com/minio/minio-go/v7 v7.0.5/go.mod h1:TA0CQCjJZHM5SJj9IjqR0NmpmQJ6bCbXif github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= +github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.0/go.mod h1:r5y0WgCag0dTj/qiHkHrXAcKQ/f5GMOZaEGdoxxnJ4I= github.com/nats-io/nats-server/v2 v2.1.7/go.mod h1:rbRrRE/Iv93O/rUvZ9dh4NfT0Cm9HWjW/BqOWLGgYiE= github.com/nats-io/nats-streaming-server v0.18.0/go.mod h1:Y9Aiif2oANuoKazQrs4wXtF3jqt6p97ODQg68lR5TnY= -github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nats.go v1.10.0 h1:L8qnKaofSfNFbXg0C5F71LdjPRnmQwSsA4ukmkt1TvY= github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE= -github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.4 h1:aEsHIssIk6ETN5m2/MD8Y4B2X7FfXrBAUdkyRvbVYzA= github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/stan.go v0.7.0/go.mod h1:Ci6mUIpGQTjl++MqK2XzkWI/0vF+Bl72uScx7ejSYmU= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw= -github.com/nrdcg/auroradns v1.0.1/go.mod h1:y4pc0i9QXYlFCWrhWrUSIETnZgrf4KuwjDIWmmXo3JI= -github.com/nrdcg/desec v0.5.0/go.mod h1:2ejvMazkav1VdDbv2HeQO7w+Ta1CGHqzQr27ZBYTuEQ= github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ= github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ= -github.com/nrdcg/goinwx v0.7.0/go.mod h1:4tKJOCi/1lTxuw9/yB2Ez0aojwtUCSkckjc22eALpqE= github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.3/go.mod h1:YZeBtGzYYEsCHp2LST/u/0NDwGkRoBtmn1cIWCJiS6M= @@ -513,7 +394,6 @@ github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwU github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -521,14 +401,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -562,7 +440,6 @@ github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516 h1:ofR1ZdrNSkiWcMsRrubK9tb2/SlZVWttAfqUjJi6QYc= github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -571,12 +448,9 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -586,14 +460,11 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw= github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE= -github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf h1:Z2X3Os7oRzpdJ75iPqWZc0HeJWFYNCvKsfpQwFpRNTA= github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= -github.com/transip/gotransip/v6 v6.0.2/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok= @@ -607,26 +478,18 @@ github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= -github.com/vultr/govultr v0.4.2/go.mod h1:TUuUizMOFc7z+PNMssb6iGjKjQfpw5arIaOLfocVudQ= github.com/xanzy/go-gitlab v0.35.1 h1:jJSgT0NxjCvrSZf7Gvn2NxxV9xAYkTjYrKW8XwWhrfY= github.com/xanzy/go-gitlab v0.35.1/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= -github.com/xanzy/go-gitlab v0.38.1 h1:st5/Ag4h8CqVfp3LpOWW0Jd4jYHTGETwu0KksYDPnYE= -github.com/xanzy/go-gitlab v0.38.1/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/xlab/treeprint v1.0.0 h1:J0TkWtiuYgtdlrkkrDLISYBQ92M+X5m4LrIIMKrbDTs= -github.com/xlab/treeprint v1.0.0/go.mod h1:IoImgRak9i3zJyuxOKUP1v4UZd1tMoKkq/Cimt1uhCg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -639,51 +502,27 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002094018-c90954cbb977 h1:yH6opeNE+0SY+7pXT4gclZUoKHogXeC2EvOSHGOMGPU= golang.org/x/crypto v0.0.0-20201002094018-c90954cbb977/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -726,7 +565,6 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -738,9 +576,7 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191011234655-491137f69257/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191027093000-83d349e8ac1a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191109021931-daa7c04131f5/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -757,7 +593,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 h1:YfxMZzv3PjGonQYNUaeU2+DhAdqOxerQ30JFB6WgAXo= golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -777,6 +612,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -784,11 +620,8 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -799,18 +632,13 @@ golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -843,8 +671,6 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -859,9 +685,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -871,7 +695,6 @@ golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -898,6 +721,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -926,7 +750,6 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -980,12 +803,9 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw= gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= @@ -993,21 +813,13 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y= gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= -gopkg.in/telegram-bot-api.v4 v4.6.4/go.mod h1:5DpGO5dbumb40px+dXcwCpcjmeHNYLpk0bp3XRNvWDM= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From ebeba220293138fe9ba7a07438ce85435e0300b7 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Thu, 15 Oct 2020 15:16:23 +0100 Subject: [PATCH 4/6] Add README.md --- chat/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 chat/README.md diff --git a/chat/README.md b/chat/README.md new file mode 100644 index 0000000..19fb752 --- /dev/null +++ b/chat/README.md @@ -0,0 +1,5 @@ +# Chat Service + +The chat service is an example Micro service which leverages bidirectional streaming, the store and events to build a chat backend. There is both a server and client which can be run together to demonstrate the application (see client/main.go for more instructions on running the service). + +The service is documented inline and is designed to act as a reference for the events package. \ No newline at end of file From b3a93ce52a4452c3ee401c7fe9924f6b76d64fd9 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 16 Oct 2020 10:28:40 +0100 Subject: [PATCH 5/6] Chat add support for CLI --- chat/README.md | 37 ++++++++- chat/handler/handler.go | 75 +++++++++++++---- chat/proto/chat.pb.go | 161 ++++++++++++++++++++++++++++++------ chat/proto/chat.pb.micro.go | 19 +++++ chat/proto/chat.proto | 19 +++++ 5 files changed, 270 insertions(+), 41 deletions(-) diff --git a/chat/README.md b/chat/README.md index 19fb752..7410db8 100644 --- a/chat/README.md +++ b/chat/README.md @@ -2,4 +2,39 @@ The chat service is an example Micro service which leverages bidirectional streaming, the store and events to build a chat backend. There is both a server and client which can be run together to demonstrate the application (see client/main.go for more instructions on running the service). -The service is documented inline and is designed to act as a reference for the events package. \ No newline at end of file +The service is documented inline and is designed to act as a reference for the events package. + +### Calling the service + +You can call the service via the CLI: + +Create a chat: +```bash +> micro chat new --user_ids=JohnBarry +{ + "chat_id": "3c9ea66c-d516-45d4-abe8-082089e18b27" +} +``` + +Send a message to the chat: +```bash +> micro chat send --chat_id=bed4f0f0-da12-46d2-90d2-17ae1714a214 --user_id=John --subject=Hello --text='Hey Barry' +{} +``` + +View the chat history +```bash +> micro chat history --chat_id=bed4f0f0-da12-46d2-90d2-17ae1714a214 +{ + "messages": [ + { + "id": "a61284a8-f471-4734-9192-640d89762e98", + "client_id": "6ba0d2a6-96fa-47d8-8f6f-7f75b4cc8b3e", + "chat_id": "bed4f0f0-da12-46d2-90d2-17ae1714a214", + "user_id": "John", + "subject": "Hello", + "text": "Hey Barry" + } + ] +} +``` \ No newline at end of file diff --git a/chat/handler/handler.go b/chat/handler/handler.go index da83307..c454513 100644 --- a/chat/handler/handler.go +++ b/chat/handler/handler.go @@ -138,6 +138,38 @@ func (h *handler) History(ctx context.Context, req *pb.HistoryRequest, rsp *pb.H return nil } +// Send a single message to the chat, designed for ease of use via the API / CLI +func (h *handler) Send(ctx context.Context, req *pb.SendRequest, rsp *pb.SendResponse) error { + // validate the request + if len(req.ChatId) == 0 { + return errors.BadRequest("chat.Send.MissingChatID", "ChatID is missing") + } + if len(req.UserId) == 0 { + return errors.BadRequest("chat.Send.MissingUserID", "UserID is missing") + } + if len(req.Text) == 0 { + return errors.BadRequest("chat.Send.MissingText", "Text is missing") + } + + // construct the message + msg := &pb.Message{ + Id: uuid.New().String(), + ClientId: req.ClientId, + ChatId: req.ChatId, + UserId: req.UserId, + Subject: req.Subject, + Text: req.Text, + } + + // default the client id if not provided + if len(msg.ClientId) == 0 { + msg.ClientId = uuid.New().String() + } + + // create the message + return h.createMessage(msg) +} + // Connect to a chat using a bidirectional stream enabling the client to send and recieve messages // over a single RPC. When a message is sent on the stream, it will be added to the chat history // and sent to the other connected users. When opening the connection, the client should provide @@ -236,28 +268,39 @@ func (h *handler) Connect(ctx context.Context, stream pb.Chat_ConnectStream) err // an error occured in another goroutine, terminate the stream return err case msg := <-msgChan: - // a message was recieved from the client. validate it hasn't been recieved before - if _, err := store.Read(messageStoreKeyPrefix + msg.ClientId); err == nil { - // the message has already been processed - continue - } else if err != store.ErrNotFound { - // an unexpected error occured - return err - } - // set the defaults msg.UserId = userID msg.ChatId = chatID - // send the message to the event stream - if err := events.Publish(chatEventKeyPrefix+chatID, msg); err != nil { - return err - } - - // record the messages client id - if err := store.Write(&store.Record{Key: messageStoreKeyPrefix + msg.ClientId}); err != nil { + // create the message + if err := h.createMessage(msg); err != nil { return err } } } } + +// createMessage is a helper function which creates a message in the event stream. It handles the +// logic for ensuring client id is unique. +func (h *handler) createMessage(msg *pb.Message) error { + // a message was recieved from the client. validate it hasn't been recieved before + if _, err := store.Read(messageStoreKeyPrefix + msg.ClientId); err == nil { + // the message has already been processed + return nil + } else if err != store.ErrNotFound { + // an unexpected error occured + return err + } + + // send the message to the event stream + if err := events.Publish(chatEventKeyPrefix+msg.ChatId, msg); err != nil { + return err + } + + // record the messages client id + if err := store.Write(&store.Record{Key: messageStoreKeyPrefix + msg.ClientId}); err != nil { + return err + } + + return nil +} diff --git a/chat/proto/chat.pb.go b/chat/proto/chat.pb.go index 8806d76..cca8e16 100644 --- a/chat/proto/chat.pb.go +++ b/chat/proto/chat.pb.go @@ -182,6 +182,115 @@ func (m *HistoryResponse) GetMessages() []*Message { return nil } +// SendRequest contains a single message to send to a chat +type SendRequest struct { + // a client side id, should be validated by the server to make the request retry safe + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + // id of the chat the message is being sent to / from + ChatId string `protobuf:"bytes,2,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"` + // id of the user who sent the message + UserId string `protobuf:"bytes,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + // subject of the message + Subject string `protobuf:"bytes,4,opt,name=subject,proto3" json:"subject,omitempty"` + // text of the message + Text string `protobuf:"bytes,5,opt,name=text,proto3" json:"text,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SendRequest) Reset() { *m = SendRequest{} } +func (m *SendRequest) String() string { return proto.CompactTextString(m) } +func (*SendRequest) ProtoMessage() {} +func (*SendRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_825b1469f80f958d, []int{4} +} + +func (m *SendRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SendRequest.Unmarshal(m, b) +} +func (m *SendRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SendRequest.Marshal(b, m, deterministic) +} +func (m *SendRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SendRequest.Merge(m, src) +} +func (m *SendRequest) XXX_Size() int { + return xxx_messageInfo_SendRequest.Size(m) +} +func (m *SendRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SendRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SendRequest proto.InternalMessageInfo + +func (m *SendRequest) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *SendRequest) GetChatId() string { + if m != nil { + return m.ChatId + } + return "" +} + +func (m *SendRequest) GetUserId() string { + if m != nil { + return m.UserId + } + return "" +} + +func (m *SendRequest) GetSubject() string { + if m != nil { + return m.Subject + } + return "" +} + +func (m *SendRequest) GetText() string { + if m != nil { + return m.Text + } + return "" +} + +// SendResponse is a blank message returned when a message is successfully created +type SendResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SendResponse) Reset() { *m = SendResponse{} } +func (m *SendResponse) String() string { return proto.CompactTextString(m) } +func (*SendResponse) ProtoMessage() {} +func (*SendResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_825b1469f80f958d, []int{5} +} + +func (m *SendResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SendResponse.Unmarshal(m, b) +} +func (m *SendResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SendResponse.Marshal(b, m, deterministic) +} +func (m *SendResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SendResponse.Merge(m, src) +} +func (m *SendResponse) XXX_Size() int { + return xxx_messageInfo_SendResponse.Size(m) +} +func (m *SendResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SendResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SendResponse proto.InternalMessageInfo + // Message sent to a chat type Message struct { // id of the message, allocated by the server @@ -207,7 +316,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_825b1469f80f958d, []int{4} + return fileDescriptor_825b1469f80f958d, []int{6} } func (m *Message) XXX_Unmarshal(b []byte) error { @@ -282,33 +391,37 @@ func init() { proto.RegisterType((*NewResponse)(nil), "chat.NewResponse") proto.RegisterType((*HistoryRequest)(nil), "chat.HistoryRequest") proto.RegisterType((*HistoryResponse)(nil), "chat.HistoryResponse") + proto.RegisterType((*SendRequest)(nil), "chat.SendRequest") + proto.RegisterType((*SendResponse)(nil), "chat.SendResponse") proto.RegisterType((*Message)(nil), "chat.Message") } func init() { proto.RegisterFile("chat/proto/chat.proto", fileDescriptor_825b1469f80f958d) } var fileDescriptor_825b1469f80f958d = []byte{ - // 351 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xcd, 0x4e, 0xf2, 0x40, - 0x14, 0xcd, 0xd0, 0x7e, 0x1d, 0xb8, 0xe4, 0x43, 0x9d, 0x48, 0x1c, 0x71, 0x43, 0xba, 0xd0, 0x22, - 0x09, 0x35, 0x98, 0xb8, 0xd1, 0x8d, 0xb2, 0x91, 0x85, 0x2c, 0xba, 0x74, 0x43, 0x4a, 0x3b, 0x81, - 0x31, 0xd2, 0xc1, 0xce, 0x54, 0xf4, 0x49, 0x7c, 0x0c, 0x5f, 0xd1, 0xcc, 0x4c, 0xf9, 0xa9, 0x89, - 0xbb, 0xf3, 0x33, 0xf7, 0xf6, 0xdc, 0x93, 0x42, 0x3b, 0x59, 0xc4, 0x2a, 0x5c, 0xe5, 0x42, 0x89, - 0x50, 0xc3, 0x81, 0x81, 0xc4, 0xd5, 0xd8, 0xbf, 0x00, 0x98, 0xb0, 0x75, 0xc4, 0xde, 0x0a, 0x26, - 0x15, 0x39, 0x85, 0x7a, 0x21, 0x59, 0x3e, 0xe5, 0xa9, 0xa4, 0xa8, 0xeb, 0x04, 0x8d, 0x08, 0x6b, - 0x3e, 0x4e, 0xa5, 0x7f, 0x0e, 0x4d, 0xf3, 0x50, 0xae, 0x44, 0x26, 0x19, 0x39, 0x01, 0xac, 0xe7, - 0xa7, 0x3c, 0xa5, 0xa8, 0x8b, 0x82, 0x46, 0xe4, 0x69, 0x3a, 0x4e, 0xfd, 0x1e, 0xb4, 0x1e, 0xb9, - 0x54, 0x22, 0xff, 0xdc, 0x2c, 0xfd, 0xf3, 0xe9, 0x1d, 0x1c, 0x6c, 0x9f, 0x96, 0x6b, 0x7b, 0x50, - 0x5f, 0x32, 0x29, 0xe3, 0x39, 0xb3, 0x01, 0x9a, 0xc3, 0xff, 0x03, 0x93, 0xf9, 0xc9, 0xaa, 0xd1, - 0xd6, 0xf6, 0xbf, 0x11, 0xe0, 0x52, 0x25, 0x2d, 0xa8, 0x6d, 0xb7, 0xd7, 0x78, 0x4a, 0xce, 0xa0, - 0x91, 0xbc, 0x72, 0x96, 0x99, 0x8f, 0xd6, 0x8c, 0x5c, 0xb7, 0xc2, 0x38, 0xdd, 0xcf, 0xe3, 0xec, - 0xe7, 0xd1, 0x46, 0x79, 0x3d, 0x75, 0xad, 0x61, 0x8f, 0xd7, 0x86, 0xd4, 0xcb, 0x62, 0x45, 0xff, - 0x75, 0x51, 0xe0, 0x44, 0x9e, 0xa6, 0xf7, 0x8a, 0x50, 0xc0, 0xb2, 0x98, 0xbd, 0xb0, 0x44, 0x51, - 0xcf, 0x4c, 0x6c, 0x28, 0x21, 0xe0, 0x2a, 0xf6, 0xa1, 0x28, 0x36, 0xb2, 0xc1, 0xc3, 0x2f, 0x04, - 0xee, 0x68, 0x11, 0x2b, 0x72, 0x09, 0xce, 0x84, 0xad, 0xc9, 0xa1, 0x3d, 0x6d, 0xd7, 0x7f, 0xe7, - 0x68, 0x4f, 0x29, 0x1b, 0xb9, 0x01, 0x5c, 0x96, 0x44, 0x8e, 0xad, 0x5b, 0xad, 0xb7, 0xd3, 0xfe, - 0xa5, 0x96, 0x73, 0x7d, 0xc0, 0x23, 0x91, 0x65, 0x3a, 0x4b, 0xb5, 0xc2, 0x4e, 0x95, 0x06, 0xe8, - 0x0a, 0x3d, 0xf4, 0x9f, 0x7b, 0x73, 0xae, 0x16, 0xc5, 0x6c, 0x90, 0x88, 0x65, 0xb8, 0xe4, 0x49, - 0x2e, 0x42, 0xc9, 0xf2, 0x77, 0x9e, 0x30, 0x19, 0xee, 0x7e, 0x9f, 0x5b, 0x0d, 0x67, 0x9e, 0xc1, - 0xd7, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x53, 0xab, 0xf2, 0x77, 0x58, 0x02, 0x00, 0x00, + // 370 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcf, 0x4e, 0x3a, 0x31, + 0x10, 0xc7, 0xd3, 0xdd, 0xfd, 0x6d, 0x61, 0xf8, 0x89, 0xda, 0x48, 0x58, 0xd7, 0x0b, 0xe9, 0x41, + 0x41, 0x23, 0x18, 0x4c, 0x3c, 0x79, 0x31, 0x5c, 0xe4, 0x20, 0x87, 0xf5, 0x01, 0xc8, 0x42, 0x1b, + 0x59, 0xa3, 0xbb, 0x48, 0x4b, 0xd0, 0x57, 0xf0, 0x65, 0x7c, 0x0b, 0x9f, 0xcb, 0xf4, 0x0f, 0xd0, + 0x35, 0x72, 0x9b, 0xf9, 0xce, 0x74, 0xfa, 0xf9, 0x76, 0x0a, 0x8d, 0xe9, 0x2c, 0x95, 0xbd, 0xf9, + 0xa2, 0x90, 0x45, 0x4f, 0x85, 0x5d, 0x1d, 0x92, 0x40, 0xc5, 0xf4, 0x0c, 0x60, 0xc4, 0x57, 0x09, + 0x7f, 0x5b, 0x72, 0x21, 0xc9, 0x31, 0x54, 0x96, 0x82, 0x2f, 0xc6, 0x19, 0x13, 0x11, 0x6a, 0xf9, + 0xed, 0x6a, 0x82, 0x55, 0x3e, 0x64, 0x82, 0x9e, 0x42, 0x4d, 0x37, 0x8a, 0x79, 0x91, 0x0b, 0x4e, + 0x9a, 0x80, 0xd5, 0xf9, 0x71, 0xc6, 0x22, 0xd4, 0x42, 0xed, 0x6a, 0x12, 0xaa, 0x74, 0xc8, 0x68, + 0x07, 0xea, 0xf7, 0x99, 0x90, 0xc5, 0xe2, 0x63, 0x3d, 0x74, 0x67, 0xeb, 0x2d, 0xec, 0x6f, 0x5a, + 0xed, 0xd8, 0x0e, 0x54, 0x5e, 0xb9, 0x10, 0xe9, 0x13, 0x37, 0x00, 0xb5, 0xfe, 0x5e, 0x57, 0x33, + 0x3f, 0x18, 0x35, 0xd9, 0x94, 0xe9, 0x27, 0x82, 0xda, 0x23, 0xcf, 0xd9, 0xfa, 0x9a, 0x13, 0xa8, + 0x4e, 0x5f, 0x32, 0x9e, 0x3b, 0x17, 0x55, 0x8c, 0x30, 0x64, 0x2e, 0x83, 0xe7, 0x32, 0xa8, 0x82, + 0x75, 0x1c, 0xf9, 0xa6, 0x60, 0x0c, 0x93, 0x08, 0xb0, 0x58, 0x4e, 0x9e, 0xf9, 0x54, 0x46, 0x81, + 0x2e, 0xac, 0x53, 0x42, 0x20, 0x90, 0xfc, 0x5d, 0x46, 0xff, 0xb4, 0xac, 0x63, 0x5a, 0x87, 0xff, + 0x86, 0xc5, 0xf8, 0xa0, 0x5f, 0x08, 0xb0, 0x45, 0x26, 0x75, 0xf0, 0x36, 0x44, 0x5e, 0xc6, 0xca, + 0xa0, 0xde, 0x6e, 0x50, 0x7f, 0x17, 0x68, 0x50, 0x02, 0x6d, 0x02, 0x16, 0x6a, 0x58, 0x6a, 0x88, + 0xfc, 0x24, 0x54, 0xe9, 0x9d, 0x74, 0x1d, 0x84, 0x7f, 0x3b, 0xc0, 0x5b, 0x07, 0xfd, 0x6f, 0x04, + 0xc1, 0x60, 0x96, 0x4a, 0x72, 0x0e, 0xfe, 0x88, 0xaf, 0xc8, 0x81, 0x79, 0xf7, 0xed, 0xe7, 0x88, + 0x0f, 0x1d, 0xc5, 0xae, 0xeb, 0x06, 0xb0, 0xdd, 0x20, 0x39, 0x32, 0xd5, 0xf2, 0xee, 0xe3, 0xc6, + 0x2f, 0xd5, 0x9e, 0xbb, 0x84, 0x40, 0x3d, 0x17, 0xb1, 0x23, 0x9d, 0x35, 0xc6, 0xc4, 0x95, 0x6c, + 0xfb, 0x05, 0xe0, 0x41, 0x91, 0xe7, 0x0a, 0xbd, 0xfc, 0x1d, 0xe2, 0x72, 0xda, 0x46, 0x57, 0x68, + 0x12, 0xea, 0xef, 0x7d, 0xfd, 0x13, 0x00, 0x00, 0xff, 0xff, 0x81, 0x53, 0x8a, 0xc9, 0xf7, 0x02, + 0x00, 0x00, } diff --git a/chat/proto/chat.pb.micro.go b/chat/proto/chat.pb.micro.go index 482e3e3..5e6ec91 100644 --- a/chat/proto/chat.pb.micro.go +++ b/chat/proto/chat.pb.micro.go @@ -48,6 +48,8 @@ type ChatService interface { New(ctx context.Context, in *NewRequest, opts ...client.CallOption) (*NewResponse, error) // History returns the historical messages in a chat History(ctx context.Context, in *HistoryRequest, opts ...client.CallOption) (*HistoryResponse, error) + // Send a single message to the chat + Send(ctx context.Context, in *SendRequest, opts ...client.CallOption) (*SendResponse, error) // Connect to a chat using a bidirectional stream enabling the client to send and recieve messages // over a single RPC. When a message is sent on the stream, it will be added to the chat history // and sent to the other connected users. When opening the connection, the client should provide @@ -87,6 +89,16 @@ func (c *chatService) History(ctx context.Context, in *HistoryRequest, opts ...c return out, nil } +func (c *chatService) Send(ctx context.Context, in *SendRequest, opts ...client.CallOption) (*SendResponse, error) { + req := c.c.NewRequest(c.name, "Chat.Send", in) + out := new(SendResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *chatService) Connect(ctx context.Context, opts ...client.CallOption) (Chat_ConnectService, error) { req := c.c.NewRequest(c.name, "Chat.Connect", &Message{}) stream, err := c.c.Stream(ctx, req, opts...) @@ -147,6 +159,8 @@ type ChatHandler interface { New(context.Context, *NewRequest, *NewResponse) error // History returns the historical messages in a chat History(context.Context, *HistoryRequest, *HistoryResponse) error + // Send a single message to the chat + Send(context.Context, *SendRequest, *SendResponse) error // Connect to a chat using a bidirectional stream enabling the client to send and recieve messages // over a single RPC. When a message is sent on the stream, it will be added to the chat history // and sent to the other connected users. When opening the connection, the client should provide @@ -158,6 +172,7 @@ func RegisterChatHandler(s server.Server, hdlr ChatHandler, opts ...server.Handl type chat interface { New(ctx context.Context, in *NewRequest, out *NewResponse) error History(ctx context.Context, in *HistoryRequest, out *HistoryResponse) error + Send(ctx context.Context, in *SendRequest, out *SendResponse) error Connect(ctx context.Context, stream server.Stream) error } type Chat struct { @@ -179,6 +194,10 @@ func (h *chatHandler) History(ctx context.Context, in *HistoryRequest, out *Hist return h.ChatHandler.History(ctx, in, out) } +func (h *chatHandler) Send(ctx context.Context, in *SendRequest, out *SendResponse) error { + return h.ChatHandler.Send(ctx, in, out) +} + func (h *chatHandler) Connect(ctx context.Context, stream server.Stream) error { return h.ChatHandler.Connect(ctx, &chatConnectStream{stream}) } diff --git a/chat/proto/chat.proto b/chat/proto/chat.proto index 981488a..991608d 100644 --- a/chat/proto/chat.proto +++ b/chat/proto/chat.proto @@ -10,6 +10,8 @@ service Chat { rpc New(NewRequest) returns (NewResponse); // History returns the historical messages in a chat rpc History(HistoryRequest) returns (HistoryResponse); + // Send a single message to the chat + rpc Send(SendRequest) returns (SendResponse); // Connect to a chat using a bidirectional stream enabling the client to send and recieve messages // over a single RPC. When a message is sent on the stream, it will be added to the chat history // and sent to the other connected users. When opening the connection, the client should provide @@ -39,6 +41,23 @@ message HistoryResponse { repeated Message messages = 1; } +// SendRequest contains a single message to send to a chat +message SendRequest { + // a client side id, should be validated by the server to make the request retry safe + string client_id = 1; + // id of the chat the message is being sent to / from + string chat_id = 2; + // id of the user who sent the message + string user_id = 3; + // subject of the message + string subject = 4; + // text of the message + string text = 5; +} + +// SendResponse is a blank message returned when a message is successfully created +message SendResponse {} + // Message sent to a chat message Message { // id of the message, allocated by the server From b9d16c678e407a2bd3199cafa34dce80f90f321f Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 16 Oct 2020 10:32:10 +0100 Subject: [PATCH 6/6] Format --- chat/handler/handler.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/chat/handler/handler.go b/chat/handler/handler.go index c454513..5d46153 100644 --- a/chat/handler/handler.go +++ b/chat/handler/handler.go @@ -5,9 +5,8 @@ import ( "sort" "strings" - "github.com/micro/micro/v3/service/context/metadata" - "github.com/google/uuid" + "github.com/micro/micro/v3/service/context/metadata" "github.com/micro/micro/v3/service/errors" "github.com/micro/micro/v3/service/events" "github.com/micro/micro/v3/service/logger"