diff --git a/README.md b/README.md
index 8aabed4e..203d8075 100644
--- a/README.md
+++ b/README.md
@@ -126,18 +126,19 @@ metadata:
### Sink Configure
Supported Sinks:
-| Sink Name | Description |
-| ---------------------------- | :-------------------------------- |
-| dingtalk | sink to dingtalk bot |
-| sls | sink to alibaba cloud sls service |
+| Sink Name | Description |
+|-----------------------------------------------------------|:----------------------------------|
+| dingtalk | sink to dingtalk bot |
+| sls | sink to alibaba cloud sls service |
| elasticsearch | sink to elasticsearch |
-| honeycomb | sink to honeycomb |
-| influxdb | sink to influxdb |
-| kafka | sink to kafka |
-| mysql | sink to mysql database |
-| wechat | sink to wechat |
-| webhook | sink to webhook |
-| mongodb | sink to mongodb |
+| honeycomb | sink to honeycomb |
+| influxdb | sink to influxdb |
+| kafka | sink to kafka |
+| mysql | sink to mysql database |
+| wechat | sink to wechat |
+| webhook | sink to webhook |
+| mongodb | sink to mongodb |
+| pulsar | sink to pulsar |
### Contributing
Please check CONTRIBUTING.md
diff --git a/common/pulsar/pulsar.go b/common/pulsar/pulsar.go
new file mode 100644
index 00000000..ffab843d
--- /dev/null
+++ b/common/pulsar/pulsar.go
@@ -0,0 +1,116 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pulsar
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "github.com/apache/pulsar-client-go/pulsar"
+ "k8s.io/klog"
+ "net/url"
+ "time"
+)
+
+type PulsarClient interface {
+ Name() string
+ Stop()
+ ProducePulsarMessage(msgData interface{}) error
+}
+
+type pulsarSink struct {
+ topic string
+ producer pulsar.Producer
+}
+
+func (p *pulsarSink) Name() string {
+ return "Apache Pulsar Sink"
+}
+
+func (p *pulsarSink) Stop() {
+ p.producer.Close()
+
+}
+
+func (p *pulsarSink) ProducePulsarMessage(msgData interface{}) error {
+ start := time.Now()
+ msgJson, err := json.Marshal(msgData)
+ if err != nil {
+ return fmt.Errorf("failed to transform the items to json : %s", err)
+ }
+ send, err := p.producer.Send(context.Background(), &pulsar.ProducerMessage{
+ Payload: msgJson,
+ Properties: nil,
+ })
+ if err != nil {
+ return fmt.Errorf("failed to produce message to Pulsar: %s", err)
+ }
+ end := time.Now()
+ klog.V(4).Infof("Exported %d data to Pulsar in %s, messageID: %s", len(msgJson), end.Sub(start), send.String())
+ return nil
+}
+
+func NewPulsarClient(uri *url.URL) (PulsarClient, error) {
+ opts, err := url.ParseQuery(uri.RawQuery)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse url's query string: %s", err)
+ }
+ klog.V(3).Infof("Pulsar opts: %v", opts)
+
+ var (
+ serviceURL []string
+ token, topic string
+ client pulsar.Client
+ )
+ if len(opts["serviceurl"]) < 1 {
+ return nil, fmt.Errorf("there is no broker assigned for connecting Pulsar")
+ }
+ serviceURL = append(serviceURL, opts["serviceurl"]...)
+
+ if len(opts["eventstopic"]) != 1 {
+ return nil, fmt.Errorf("there is no topic assigned for connecting Pulsar")
+ }
+ topic = opts["eventstopic"][0]
+
+ if len(opts["token"]) > 0 {
+ token = opts["token"][0]
+ }
+
+ if len(token) == 0 {
+ client, err = pulsar.NewClient(pulsar.ClientOptions{
+ URL: serviceURL[0],
+ })
+ if err != nil {
+ return nil, fmt.Errorf("failed to create Pulsar client: %v", err)
+ }
+ } else {
+ client, err = pulsar.NewClient(pulsar.ClientOptions{
+ URL: serviceURL[0],
+ Authentication: pulsar.NewAuthenticationToken(token),
+ })
+ if err != nil {
+ return nil, fmt.Errorf("failed to create Pulsar client: %v", err)
+ }
+ }
+
+ producer, err := client.CreateProducer(pulsar.ProducerOptions{
+ Name: "kube-eventer",
+ Topic: topic,
+ })
+
+ return &pulsarSink{
+ producer: producer,
+ }, nil
+}
diff --git a/docs/en/pulsar-sink.md b/docs/en/pulsar-sink.md
new file mode 100644
index 00000000..8ec333a9
--- /dev/null
+++ b/docs/en/pulsar-sink.md
@@ -0,0 +1,15 @@
+### Pulsar sink
+
+To use the Pulsar sink add the following flag:
+
+ --sink=Pulsar:>
+
+* `serviceurl` - Pulsar's broker or proxy.
+* `eventstopic` - Pulsar's topic for events.
+* `token` - Pulsar's JWT token, If you enable [JWT](https://pulsar.apache.org/docs/next/security-jwt/).
+
+For example,
+
+ --sink=pulsar:?serviceurl=pulsar://127.0.0.1:6650&eventstopic=persistent://public/default/event&token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
+ or
+ --sink=pulsar:?serviceurl=pulsar://127.0.0.1:6650&eventstopic=persistent://public/default/event
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 574072b7..59dd899b 100644
--- a/go.mod
+++ b/go.mod
@@ -6,12 +6,13 @@ require (
github.com/Shopify/sarama v1.22.1
github.com/alibabacloud-go/eventbridge-sdk v1.2.6
github.com/alibabacloud-go/tea-utils v1.3.7
+ github.com/apache/pulsar-client-go v0.10.0
github.com/aws/aws-sdk-go v1.34.28
github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed
github.com/go-sql-driver/mysql v1.5.0
- github.com/golang/protobuf v1.4.3
+ github.com/golang/protobuf v1.5.2
github.com/google/cadvisor v0.33.1
- github.com/google/uuid v1.1.1
+ github.com/google/uuid v1.1.2
github.com/imdario/mergo v0.3.7 // indirect
github.com/influxdata/influxdb v1.7.7
github.com/mailru/easyjson v0.7.0 // indirect
@@ -22,7 +23,7 @@ require (
github.com/riemann/riemann-go-client v0.4.0
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9
github.com/smartystreets/gunit v1.0.0 // indirect
- github.com/stretchr/testify v1.6.1
+ github.com/stretchr/testify v1.8.0
go.mongodb.org/mongo-driver v1.5.1
golang.org/x/sys v0.2.0 // indirect
gopkg.in/olivere/elastic.v3 v3.0.75
diff --git a/go.sum b/go.sum
index 97a340b6..f8a792a5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,42 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
+github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4=
+github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o=
+github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA=
+github.com/AthenZ/athenz v1.10.39 h1:mtwHTF/v62ewY2Z5KWhuZgVXftBej1/Tn80zx4DcawY=
+github.com/AthenZ/athenz v1.10.39/go.mod h1:3Tg8HLsiQZp81BJY58JBeU2BR6B/H4/0MQGfCwhHNEA=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
@@ -9,8 +45,10 @@ github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxB
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798 h1:2T/jmrHeTezcCM58lvEQXs0UpQJCo5SoGAcg+mbSTIg=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
+github.com/DataDog/zstd v1.5.0 h1:+K/VEwIAaPcHiMtQvpLD4lqW7f0Gk3xdYZmI1hD+CXo=
+github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
@@ -41,17 +79,34 @@ github.com/alibabacloud-go/tea-utils v1.3.7 h1:oWLLV21JHimM8yiQcRajMYxy+dggFW7jC
github.com/alibabacloud-go/tea-utils v1.3.7/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/aliyun/credentials-go v1.1.2 h1:qU1vwGIBb3UJ8BwunHDRFtAhS6jnQLnde/yk0+Ih2GY=
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
+github.com/apache/pulsar-client-go v0.10.0 h1:ccwjmmaCjaE6bLYnrILpm8V4WQQ8rB3J98pOW0O2nyo=
+github.com/apache/pulsar-client-go v0.10.0/go.mod h1:l9ZNSafZdle1cpyFE5CkUL3uRYJMvoHjHHLlK0kL7c8=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/ardielle/ardielle-go v1.5.2 h1:TilHTpHIQJ27R1Tl/iITBzMwiUGSlVfiVhwDNGM3Zj4=
+github.com/ardielle/ardielle-go v1.5.2/go.mod h1:I4hy1n795cUhaVt/ojz83SNVCYIGsAFAONtv2Dr7HUI=
+github.com/ardielle/ardielle-tools v1.5.4/go.mod h1:oZN+JRMnqGiIhrzkRN9l26Cej9dEx4jeNG6A+AdkShk=
github.com/aws/aws-sdk-go v1.19.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go v1.32.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPIk=
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
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 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bits-and-blooms/bitset v1.4.0 h1:+YZ8ePm+He2pU3dZlIZiOeAKfrBkXi1lSrXJ/Xzgbu8=
+github.com/bits-and-blooms/bitset v1.4.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
+github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
+github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
@@ -59,7 +114,11 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed h1:WtFFp2kd7j/ATD3dT5tdjyoXuynxHu6D0AJVG9Be1q4=
github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4wg/adLLz5xh5CmpiCA=
+github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
+github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM=
+github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU=
github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
@@ -68,12 +127,21 @@ github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
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/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
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-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@@ -89,6 +157,7 @@ github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gG
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
@@ -113,26 +182,44 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
+github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=
+github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
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.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
+github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/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=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+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 v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
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=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -144,6 +231,9 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
@@ -152,11 +242,22 @@ github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSN
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
@@ -165,17 +266,26 @@ github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU=
+github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb v1.7.7 h1:UvNzAPfBrKMENVbQ4mr4ccA9sW+W1Ihl0Yh1s0BiVAg=
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
+github.com/jawher/mow.cli v1.0.4/go.mod h1:5hQj2V8g+qYmLUVWqu4Wuja1pI57M83EChYLVZ0sMKk=
+github.com/jawher/mow.cli v1.2.0/go.mod h1:y+pcA3jBAdo/GIZx/0rFjw/K2bVEODP9rfZOfaiq8Ko=
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/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
@@ -189,6 +299,7 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/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=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@@ -197,16 +308,21 @@ github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaR
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
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/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4=
+github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
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/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+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/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/linkedin/goavro/v2 v2.9.8 h1:jN50elxBsGBDGVDEKqUlDuU1cFwJ11K/yrJCBMe/7Wg=
+github.com/linkedin/goavro/v2 v2.9.8/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -224,12 +340,17 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
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/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
+github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/olivere/elastic v6.2.23+incompatible h1:oRGUA/8fKcnkDcqLuwGb5YCzgbgEBo+Y9gamsWqZ0qU=
github.com/olivere/elastic v6.2.23+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
github.com/olivere/elastic/v7 v7.0.6 h1:BIzjaAYGL8Ur1pIPIpiYDvly4HkHrO/uakiV22WDEQQ=
@@ -238,10 +359,22 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc=
+github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
+github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
@@ -267,6 +400,7 @@ github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr
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=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@@ -287,10 +421,12 @@ github.com/riemann/riemann-go-client v0.4.0/go.mod h1:F+UlZkpX4Bd/sO5rdI2g5uqkIG
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
@@ -302,8 +438,11 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/gunit v1.0.0 h1:RyPDUFcJbvtXlhJPk7v+wnxZRY2EUokhEYl2EJOPToI=
github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs=
+github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -311,13 +450,19 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
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/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
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=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
@@ -330,17 +475,29 @@ github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhe
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+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.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.mongodb.org/mongo-driver v1.5.1 h1:9nOVLGDfOaZ9R0tBumx/BcuqkbFpyTCU2r/Po7A2azI=
go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -348,10 +505,37 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
+golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -362,18 +546,41 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/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=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/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=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc=
+golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -382,6 +589,8 @@ golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -392,98 +601,248 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-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=
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/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-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/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-20191120155948-bd437916bb0e/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=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/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/tools v0.0.0-20180828015842-6cd1fcedba52/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-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+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-20190816200558-6889da9d5479/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-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
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-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/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-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=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.56.0 h1:DPMeDvGTM54DXbPkVIZsp19fp/I2K7zwA/itHYHKo8Y=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/olivere/elastic.v3 v3.0.75 h1:u3B8p1VlHF3yNLVOlhIWFT3F1ICcHfM5V6FFJe6pPSo=
gopkg.in/olivere/elastic.v3 v3.0.75/go.mod h1:yDEuSnrM51Pc8dM5ov7U8aI/ToR3PG0llA8aRv2qmw0=
gopkg.in/olivere/elastic.v5 v5.0.81 h1:21Vu9RMT2qXVLqXINtiOhwVPYz/87+Omsxh/Re+gK4k=
gopkg.in/olivere/elastic.v5 v5.0.81/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0=
gopkg.in/olivere/elastic.v6 v6.2.23 h1:wDrXwXXecu8t/mTPbvMu8zONtTJA201IKq1RxSeEU38=
gopkg.in/olivere/elastic.v6 v6.2.23/go.mod h1:2cTT8Z+/LcArSWpCgvZqBgt3VOqXiy7v00w12Lz8bd4=
+gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+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/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.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=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.17.4 h1:HbwOhDapkguO8lTAE8OX3hdF2qp8GtpC9CW/MQATXXo=
k8s.io/api v0.17.4/go.mod h1:5qxx6vjmwUVG2nHQTKGlLts8Tbok8PzHl4vHtVFuZCA=
k8s.io/apimachinery v0.17.4 h1:UzM+38cPUJnzqSQ+E1PY4YxMHIzQyCg29LOoGfo79Zw=
@@ -498,6 +857,9 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff --git a/sinks/factory.go b/sinks/factory.go
index 503dd01e..e8d9d80a 100755
--- a/sinks/factory.go
+++ b/sinks/factory.go
@@ -27,6 +27,7 @@ import (
"github.com/AliyunContainerService/kube-eventer/sinks/log"
"github.com/AliyunContainerService/kube-eventer/sinks/mongo"
"github.com/AliyunContainerService/kube-eventer/sinks/mysql"
+ "github.com/AliyunContainerService/kube-eventer/sinks/pulsar"
"github.com/AliyunContainerService/kube-eventer/sinks/riemann"
"github.com/AliyunContainerService/kube-eventer/sinks/sls"
"github.com/AliyunContainerService/kube-eventer/sinks/webhook"
@@ -65,6 +66,8 @@ func (this *SinkFactory) Build(uri flags.Uri) (core.EventSink, error) {
return eventbridge.NewEventBridgeSink(&uri.Val)
case "mongo":
return mongo.CreateMongoSink(&uri.Val)
+ case "pulsar":
+ return pulsar.NewPulsarSink(&uri.Val)
default:
return nil, fmt.Errorf("Sink not recognized: %s", uri.Key)
}
diff --git a/sinks/pulsar/pulsar.go b/sinks/pulsar/pulsar.go
new file mode 100644
index 00000000..2218076c
--- /dev/null
+++ b/sinks/pulsar/pulsar.go
@@ -0,0 +1,93 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pulsar
+
+import (
+ "encoding/json"
+ pulsar_common "github.com/AliyunContainerService/kube-eventer/common/pulsar"
+ event_core "github.com/AliyunContainerService/kube-eventer/core"
+ "github.com/AliyunContainerService/kube-eventer/metrics/core"
+ kube_api "k8s.io/api/core/v1"
+ "k8s.io/klog"
+ "net/url"
+ "sync"
+ "time"
+)
+
+type PulsarSinkPoint struct {
+ EventValue interface{}
+ EventTimestamp time.Time
+ EventTags map[string]string
+}
+
+type pulsarSink struct {
+ pulsar_common.PulsarClient
+ sync.RWMutex
+}
+
+func (p *pulsarSink) ExportEvents(batch *event_core.EventBatch) {
+ p.Lock()
+ defer p.Unlock()
+ for _, event := range batch.Events {
+ point, err := eventToPoint(event)
+ if err != nil {
+ klog.Warningf("Failed to convert event to point: %v", err)
+ }
+
+ err = p.ProducePulsarMessage(*point)
+ if err != nil {
+ klog.Errorf("Failed to produce event message: %s", err)
+ }
+ }
+}
+
+func getEventValue(event *kube_api.Event) (string, error) {
+ bytes, err := json.MarshalIndent(event, "", " ")
+ if err != nil {
+ return "", err
+ }
+ return string(bytes), nil
+}
+
+func eventToPoint(event *kube_api.Event) (*PulsarSinkPoint, error) {
+ value, err := getEventValue(event)
+ if err != nil {
+ return nil, err
+ }
+ point := PulsarSinkPoint{
+ EventTimestamp: event.LastTimestamp.Time.UTC(),
+ EventValue: value,
+ EventTags: map[string]string{
+ "eventID": string(event.UID),
+ },
+ }
+ if event.InvolvedObject.Kind == "Pod" {
+ point.EventTags[core.LabelPodId.Key] = string(event.InvolvedObject.UID)
+ point.EventTags[core.LabelPodName.Key] = event.InvolvedObject.Name
+ }
+ point.EventTags[core.LabelHostname.Key] = event.Source.Host
+ return &point, nil
+}
+
+func NewPulsarSink(uri *url.URL) (event_core.EventSink, error) {
+ client, err := pulsar_common.NewPulsarClient(uri)
+ if err != nil {
+ return nil, err
+ }
+
+ return &pulsarSink{
+ PulsarClient: client,
+ }, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/LICENSE b/vendor/github.com/apache/pulsar-client-go/LICENSE
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/apache/pulsar-client-go/NOTICE b/vendor/github.com/apache/pulsar-client-go/NOTICE
new file mode 100644
index 00000000..92236a67
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/NOTICE
@@ -0,0 +1,6 @@
+
+Apache Pulsar
+Copyright 2017-2019 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/auth.go b/vendor/github.com/apache/pulsar-client-go/oauth2/auth.go
new file mode 100644
index 00000000..d44bd350
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/auth.go
@@ -0,0 +1,133 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/apache/pulsar-client-go/oauth2/clock"
+ "github.com/golang-jwt/jwt"
+ "golang.org/x/oauth2"
+)
+
+const (
+ ClaimNameUserName = "https://pulsar.apache.org/username"
+ ClaimNameName = "name"
+ ClaimNameSubject = "sub"
+)
+
+// Flow abstracts an OAuth 2.0 authentication and authorization flow
+type Flow interface {
+ // Authorize obtains an authorization grant based on an OAuth 2.0 authorization flow.
+ // The method returns a grant which may contain an initial access token.
+ Authorize(audience string) (*AuthorizationGrant, error)
+}
+
+// AuthorizationGrantRefresher refreshes OAuth 2.0 authorization grant
+type AuthorizationGrantRefresher interface {
+ // Refresh refreshes an authorization grant to contain a fresh access token
+ Refresh(grant *AuthorizationGrant) (*AuthorizationGrant, error)
+}
+
+type AuthorizationGrantType string
+
+const (
+ // GrantTypeClientCredentials represents a client credentials grant
+ GrantTypeClientCredentials AuthorizationGrantType = "client_credentials"
+
+ // GrantTypeDeviceCode represents a device code grant
+ GrantTypeDeviceCode AuthorizationGrantType = "device_code"
+)
+
+// AuthorizationGrant is a credential representing the resource owner's authorization
+// to access its protected resources, and is used by the client to obtain an access token
+type AuthorizationGrant struct {
+ // Type describes the type of authorization grant represented by this structure
+ Type AuthorizationGrantType `json:"type"`
+
+ // Audience is the intended audience of the access tokens
+ Audience string `json:"audience,omitempty"`
+
+ // ClientID is an OAuth2 client identifier used by some flows
+ ClientID string `json:"client_id,omitempty"`
+
+ // ClientCredentials is credentials data for the client credentials grant type
+ ClientCredentials *KeyFile `json:"client_credentials,omitempty"`
+
+ // the token endpoint
+ TokenEndpoint string `json:"token_endpoint"`
+
+ // Token contains an access token in the client credentials grant type,
+ // and a refresh token in the device authorization grant type
+ Token *oauth2.Token `json:"token,omitempty"`
+
+ // Scopes contains the scopes associated with the grant, or the scopes
+ // to request in the client credentials grant type
+ Scopes []string `json:"scopes,omitempty"`
+}
+
+// TokenResult holds token information
+type TokenResult struct {
+ AccessToken string `json:"access_token"`
+ IDToken string `json:"id_token"`
+ RefreshToken string `json:"refresh_token"`
+ ExpiresIn int `json:"expires_in"`
+}
+
+// Issuer holds information about the issuer of tokens
+type Issuer struct {
+ IssuerEndpoint string
+ ClientID string
+ Audience string
+}
+
+func convertToOAuth2Token(token *TokenResult, clock clock.Clock) oauth2.Token {
+ return oauth2.Token{
+ AccessToken: token.AccessToken,
+ TokenType: "bearer",
+ RefreshToken: token.RefreshToken,
+ Expiry: clock.Now().Add(time.Duration(token.ExpiresIn) * time.Second),
+ }
+}
+
+// ExtractUserName extracts the username claim from an authorization grant
+// conforms to draft-ietf-oauth-access-token-jwt
+func ExtractUserName(token oauth2.Token) (string, error) {
+ p := jwt.Parser{}
+ claims := jwt.MapClaims{}
+ if _, _, err := p.ParseUnverified(token.AccessToken, claims); err != nil {
+ return "", fmt.Errorf("unable to decode the access token: %v", err)
+ }
+ username, ok := claims[ClaimNameUserName]
+ if !ok {
+ username, ok = claims[ClaimNameName]
+ }
+ if !ok {
+ username, ok = claims[ClaimNameSubject]
+ }
+ if !ok {
+ return "", fmt.Errorf("access token doesn't contain a username claim")
+ }
+ switch v := username.(type) {
+ case string:
+ return v, nil
+ default:
+ return "", fmt.Errorf("access token contains an unsupported username claim")
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/authorization_tokenretriever.go b/vendor/github.com/apache/pulsar-client-go/oauth2/authorization_tokenretriever.go
new file mode 100644
index 00000000..cc9d3269
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/authorization_tokenretriever.go
@@ -0,0 +1,353 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "mime"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// TokenRetriever implements AuthTokenExchanger in order to facilitate getting
+// Tokens
+type TokenRetriever struct {
+ transport HTTPAuthTransport
+}
+
+// AuthorizationTokenResponse is the HTTP response when asking for a new token.
+// Note that not all fields will contain data based on what kind of request was
+// sent
+type AuthorizationTokenResponse struct {
+ AccessToken string `json:"access_token"`
+ ExpiresIn int `json:"expires_in"`
+ IDToken string `json:"id_token"`
+ RefreshToken string `json:"refresh_token"`
+ TokenType string `json:"token_type"`
+}
+
+// AuthorizationCodeExchangeRequest is used to request the exchange of an
+// authorization code for a token
+type AuthorizationCodeExchangeRequest struct {
+ TokenEndpoint string
+ ClientID string
+ CodeVerifier string
+ Code string
+ RedirectURI string
+}
+
+// RefreshTokenExchangeRequest is used to request the exchange of a refresh
+// token for a refreshed token
+type RefreshTokenExchangeRequest struct {
+ TokenEndpoint string
+ ClientID string
+ RefreshToken string
+}
+
+// ClientCredentialsExchangeRequest is used to request the exchange of
+// client credentials for a token
+type ClientCredentialsExchangeRequest struct {
+ TokenEndpoint string
+ ClientID string
+ ClientSecret string
+ Audience string
+ Scopes []string
+}
+
+// DeviceCodeExchangeRequest is used to request the exchange of
+// a device code for a token
+type DeviceCodeExchangeRequest struct {
+ TokenEndpoint string
+ ClientID string
+ DeviceCode string
+ PollInterval time.Duration
+}
+
+// TokenErrorResponse is used to parse error responses from the token endpoint
+type TokenErrorResponse struct {
+ Error string `json:"error"`
+ ErrorDescription string `json:"error_description"`
+}
+
+type TokenError struct {
+ ErrorCode string
+ ErrorDescription string
+}
+
+func (e *TokenError) Error() string {
+ if e.ErrorDescription != "" {
+ return fmt.Sprintf("%s (%s)", e.ErrorDescription, e.ErrorCode)
+ }
+ return e.ErrorCode
+}
+
+// HTTPAuthTransport abstracts how an HTTP exchange request is sent and received
+type HTTPAuthTransport interface {
+ Do(request *http.Request) (*http.Response, error)
+}
+
+// NewTokenRetriever allows a TokenRetriever the internal of a new
+// TokenRetriever to be easily set up
+func NewTokenRetriever(authTransport HTTPAuthTransport) *TokenRetriever {
+ return &TokenRetriever{
+ transport: authTransport,
+ }
+}
+
+// newExchangeCodeRequest builds a new AuthTokenRequest wrapped in an
+// http.Request
+func (ce *TokenRetriever) newExchangeCodeRequest(
+ req AuthorizationCodeExchangeRequest) (*http.Request, error) {
+ uv := url.Values{}
+ uv.Set("grant_type", "authorization_code")
+ uv.Set("client_id", req.ClientID)
+ uv.Set("code_verifier", req.CodeVerifier)
+ uv.Set("code", req.Code)
+ uv.Set("redirect_uri", req.RedirectURI)
+
+ euv := uv.Encode()
+
+ request, err := http.NewRequest("POST",
+ req.TokenEndpoint,
+ strings.NewReader(euv),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ request.Header.Add("Content-Length", strconv.Itoa(len(euv)))
+
+ return request, nil
+}
+
+// newDeviceCodeExchangeRequest builds a new DeviceCodeExchangeRequest wrapped in an
+// http.Request
+func (ce *TokenRetriever) newDeviceCodeExchangeRequest(
+ req DeviceCodeExchangeRequest) (*http.Request, error) {
+ uv := url.Values{}
+ uv.Set("grant_type", "urn:ietf:params:oauth:grant-type:device_code")
+ uv.Set("client_id", req.ClientID)
+ uv.Set("device_code", req.DeviceCode)
+ euv := uv.Encode()
+
+ request, err := http.NewRequest("POST",
+ req.TokenEndpoint,
+ strings.NewReader(euv),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ request.Header.Add("Content-Length", strconv.Itoa(len(euv)))
+
+ return request, nil
+}
+
+// newRefreshTokenRequest builds a new RefreshTokenRequest wrapped in an
+// http.Request
+func (ce *TokenRetriever) newRefreshTokenRequest(req RefreshTokenExchangeRequest) (*http.Request, error) {
+ uv := url.Values{}
+ uv.Set("grant_type", "refresh_token")
+ uv.Set("client_id", req.ClientID)
+ uv.Set("refresh_token", req.RefreshToken)
+
+ euv := uv.Encode()
+
+ request, err := http.NewRequest("POST",
+ req.TokenEndpoint,
+ strings.NewReader(euv),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ request.Header.Add("Content-Length", strconv.Itoa(len(euv)))
+
+ return request, nil
+}
+
+// newClientCredentialsRequest builds a new ClientCredentialsExchangeRequest wrapped in an
+// http.Request
+func (ce *TokenRetriever) newClientCredentialsRequest(req ClientCredentialsExchangeRequest) (*http.Request, error) {
+ uv := url.Values{}
+ uv.Set("grant_type", "client_credentials")
+ uv.Set("client_id", req.ClientID)
+ uv.Set("client_secret", req.ClientSecret)
+ if len(req.Scopes) > 0 {
+ uv.Set("scope", strings.Join(req.Scopes, " "))
+ }
+ if req.Audience != "" {
+ // Audience is an Auth0 extension; other providers use scopes to similar effect.
+ uv.Set("audience", req.Audience)
+ }
+
+ euv := uv.Encode()
+
+ request, err := http.NewRequest("POST",
+ req.TokenEndpoint,
+ strings.NewReader(euv),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ request.Header.Add("Content-Length", strconv.Itoa(len(euv)))
+
+ return request, nil
+}
+
+// ExchangeCode uses the AuthCodeExchangeRequest to exchange an authorization
+// code for tokens
+func (ce *TokenRetriever) ExchangeCode(req AuthorizationCodeExchangeRequest) (*TokenResult, error) {
+ request, err := ce.newExchangeCodeRequest(req)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := ce.transport.Do(request)
+ if err != nil {
+ return nil, err
+ }
+
+ return ce.handleAuthTokensResponse(response)
+}
+
+// handleAuthTokensResponse takes care of checking an http.Response that has
+// auth tokens for errors and parsing the raw body to a TokenResult struct
+func (ce *TokenRetriever) handleAuthTokensResponse(resp *http.Response) (*TokenResult, error) {
+ if resp.Body != nil {
+ defer resp.Body.Close()
+ }
+ if resp.StatusCode < 200 || resp.StatusCode > 299 {
+ cth := resp.Header.Get("Content-Type")
+ if cth == "" {
+ cth = "application/json"
+ }
+ ct, _, err := mime.ParseMediaType(cth)
+ if err != nil {
+ return nil, fmt.Errorf("unprocessable content type: %s: %w", cth, err)
+ }
+ if ct == "application/json" {
+ er := TokenErrorResponse{}
+ err := json.NewDecoder(resp.Body).Decode(&er)
+ if err != nil {
+ return nil, err
+ }
+ return nil, &TokenError{ErrorCode: er.Error, ErrorDescription: er.ErrorDescription}
+ }
+ return nil, fmt.Errorf("a non-success status code was received: %d", resp.StatusCode)
+ }
+
+ atr := AuthorizationTokenResponse{}
+ err := json.NewDecoder(resp.Body).Decode(&atr)
+ if err != nil {
+ return nil, err
+ }
+
+ return &TokenResult{
+ AccessToken: atr.AccessToken,
+ IDToken: atr.IDToken,
+ RefreshToken: atr.RefreshToken,
+ ExpiresIn: atr.ExpiresIn,
+ }, nil
+}
+
+// ExchangeDeviceCode uses the DeviceCodeExchangeRequest to exchange a device
+// code for tokens
+func (ce *TokenRetriever) ExchangeDeviceCode(ctx context.Context, req DeviceCodeExchangeRequest) (*TokenResult, error) {
+ for {
+ request, err := ce.newDeviceCodeExchangeRequest(req)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := ce.transport.Do(request)
+ if err != nil {
+ return nil, err
+ }
+ token, err := ce.handleAuthTokensResponse(response)
+ if err == nil {
+ return token, nil
+ }
+ terr, ok := err.(*TokenError)
+ if !ok {
+ return nil, err
+ }
+ switch terr.ErrorCode {
+ case "expired_token":
+ // The user has not authorized the device quickly enough, so the device_code has expired.
+ return nil, fmt.Errorf("the device code has expired")
+ case "access_denied":
+ // The user refused to authorize the device
+ return nil, fmt.Errorf("the device was not authorized")
+ case "authorization_pending":
+ // Still waiting for the user to take action
+ case "slow_down":
+ // You are polling too fast
+ }
+
+ select {
+ case <-time.After(req.PollInterval):
+ continue
+ case <-ctx.Done():
+ return nil, errors.New("cancelled")
+ }
+ }
+}
+
+// ExchangeRefreshToken uses the RefreshTokenExchangeRequest to exchange a
+// refresh token for refreshed tokens
+func (ce *TokenRetriever) ExchangeRefreshToken(req RefreshTokenExchangeRequest) (*TokenResult, error) {
+ request, err := ce.newRefreshTokenRequest(req)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := ce.transport.Do(request)
+ if err != nil {
+ return nil, err
+ }
+
+ return ce.handleAuthTokensResponse(response)
+}
+
+// ExchangeClientCredentials uses the ClientCredentialsExchangeRequest to exchange
+// client credentials for tokens
+func (ce *TokenRetriever) ExchangeClientCredentials(req ClientCredentialsExchangeRequest) (*TokenResult, error) {
+ request, err := ce.newClientCredentialsRequest(req)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := ce.transport.Do(request)
+ if err != nil {
+ return nil, err
+ }
+
+ return ce.handleAuthTokensResponse(response)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/cache/cache.go b/vendor/github.com/apache/pulsar-client-go/oauth2/cache/cache.go
new file mode 100644
index 00000000..b7f89b21
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/cache/cache.go
@@ -0,0 +1,142 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package cache
+
+import (
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/apache/pulsar-client-go/oauth2"
+ "github.com/apache/pulsar-client-go/oauth2/store"
+
+ "github.com/apache/pulsar-client-go/oauth2/clock"
+ xoauth2 "golang.org/x/oauth2"
+)
+
+// A CachingTokenSource is anything that can return a token, and is backed by a cache.
+type CachingTokenSource interface {
+ xoauth2.TokenSource
+
+ // InvalidateToken is called when the token is rejected by the resource server.
+ InvalidateToken() error
+}
+
+const (
+ // expiryDelta adjusts the token TTL to avoid using tokens which are almost expired
+ expiryDelta = time.Duration(60) * time.Second
+)
+
+// tokenCache implements a cache for the token associated with a specific audience.
+// it interacts with the store when the access token is near expiration or invalidated.
+// it is advisable to use a token cache instance per audience.
+type tokenCache struct {
+ clock clock.Clock
+ lock sync.Mutex
+ store store.Store
+ audience string
+ refresher oauth2.AuthorizationGrantRefresher
+ token *xoauth2.Token
+}
+
+func NewDefaultTokenCache(store store.Store, audience string,
+ refresher oauth2.AuthorizationGrantRefresher) (CachingTokenSource, error) {
+ cache := &tokenCache{
+ clock: clock.RealClock{},
+ store: store,
+ audience: audience,
+ refresher: refresher,
+ }
+ return cache, nil
+}
+
+var _ CachingTokenSource = &tokenCache{}
+
+// Token returns a valid access token, if available.
+func (t *tokenCache) Token() (*xoauth2.Token, error) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ // use the cached access token if it isn't expired
+ if t.token != nil && t.validateAccessToken(*t.token) {
+ return t.token, nil
+ }
+
+ // load from the store and use the access token if it isn't expired
+ grant, err := t.store.LoadGrant(t.audience)
+ if err != nil {
+ return nil, fmt.Errorf("LoadGrant: %v", err)
+ }
+ t.token = grant.Token
+ if t.token != nil && t.validateAccessToken(*t.token) {
+ return t.token, nil
+ }
+
+ // obtain and cache a fresh access token
+ grant, err = t.refresher.Refresh(grant)
+ if err != nil {
+ return nil, fmt.Errorf("RefreshGrant: %v", err)
+ }
+ t.token = grant.Token
+ err = t.store.SaveGrant(t.audience, *grant)
+ if err != nil {
+ // TODO log rather than throw
+ return nil, fmt.Errorf("SaveGrant: %v", err)
+ }
+
+ return t.token, nil
+}
+
+// InvalidateToken clears the access token (likely due to a response from the resource server).
+// Note that the token within the grant may contain a refresh token which should survive.
+func (t *tokenCache) InvalidateToken() error {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ previous := t.token
+ t.token = nil
+
+ // clear from the store the access token that was returned earlier (unless the store has since been updated)
+ if previous == nil || previous.AccessToken == "" {
+ return nil
+ }
+ grant, err := t.store.LoadGrant(t.audience)
+ if err != nil {
+ return fmt.Errorf("LoadGrant: %v", err)
+ }
+ if grant.Token != nil && grant.Token.AccessToken == previous.AccessToken {
+ grant.Token.Expiry = time.Unix(0, 0).Add(expiryDelta)
+ err = t.store.SaveGrant(t.audience, *grant)
+ if err != nil {
+ // TODO log rather than throw
+ return fmt.Errorf("SaveGrant: %v", err)
+ }
+ }
+ return nil
+}
+
+// validateAccessToken checks the validity of the cached access token
+func (t *tokenCache) validateAccessToken(token xoauth2.Token) bool {
+ if token.AccessToken == "" {
+ return false
+ }
+ if !token.Expiry.IsZero() && t.clock.Now().After(token.Expiry.Round(0).Add(-expiryDelta)) {
+ return false
+ }
+ return true
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/client_credentials_flow.go b/vendor/github.com/apache/pulsar-client-go/oauth2/client_credentials_flow.go
new file mode 100644
index 00000000..2252144a
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/client_credentials_flow.go
@@ -0,0 +1,161 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "net/http"
+
+ "github.com/apache/pulsar-client-go/oauth2/clock"
+
+ "github.com/pkg/errors"
+)
+
+// ClientCredentialsFlow takes care of the mechanics needed for getting an access
+// token using the OAuth 2.0 "Client Credentials Flow"
+type ClientCredentialsFlow struct {
+ options ClientCredentialsFlowOptions
+ oidcWellKnownEndpoints OIDCWellKnownEndpoints
+ keyfile *KeyFile
+ exchanger ClientCredentialsExchanger
+ clock clock.Clock
+}
+
+// ClientCredentialsProvider abstracts getting client credentials
+type ClientCredentialsProvider interface {
+ GetClientCredentials() (*KeyFile, error)
+}
+
+// ClientCredentialsExchanger abstracts exchanging client credentials for tokens
+type ClientCredentialsExchanger interface {
+ ExchangeClientCredentials(req ClientCredentialsExchangeRequest) (*TokenResult, error)
+}
+
+type ClientCredentialsFlowOptions struct {
+ KeyFile string
+ AdditionalScopes []string
+}
+
+func newClientCredentialsFlow(
+ options ClientCredentialsFlowOptions,
+ keyfile *KeyFile,
+ oidcWellKnownEndpoints OIDCWellKnownEndpoints,
+ exchanger ClientCredentialsExchanger,
+ clock clock.Clock) *ClientCredentialsFlow {
+ return &ClientCredentialsFlow{
+ options: options,
+ oidcWellKnownEndpoints: oidcWellKnownEndpoints,
+ keyfile: keyfile,
+ exchanger: exchanger,
+ clock: clock,
+ }
+}
+
+// NewDefaultClientCredentialsFlow provides an easy way to build up a default
+// client credentials flow with all the correct configuration.
+func NewDefaultClientCredentialsFlow(options ClientCredentialsFlowOptions) (*ClientCredentialsFlow, error) {
+
+ credsProvider := NewClientCredentialsProviderFromKeyFile(options.KeyFile)
+ keyFile, err := credsProvider.GetClientCredentials()
+ if err != nil {
+ return nil, errors.Wrap(err, "could not get client credentials")
+ }
+
+ wellKnownEndpoints, err := GetOIDCWellKnownEndpointsFromIssuerURL(keyFile.IssuerURL)
+ if err != nil {
+ return nil, err
+ }
+
+ tokenRetriever := NewTokenRetriever(&http.Client{})
+
+ return newClientCredentialsFlow(
+ options,
+ keyFile,
+ *wellKnownEndpoints,
+ tokenRetriever,
+ clock.RealClock{}), nil
+}
+
+var _ Flow = &ClientCredentialsFlow{}
+
+func (c *ClientCredentialsFlow) Authorize(audience string) (*AuthorizationGrant, error) {
+ var err error
+ grant := &AuthorizationGrant{
+ Type: GrantTypeClientCredentials,
+ Audience: audience,
+ ClientID: c.keyfile.ClientID,
+ ClientCredentials: c.keyfile,
+ TokenEndpoint: c.oidcWellKnownEndpoints.TokenEndpoint,
+ Scopes: c.options.AdditionalScopes,
+ }
+
+ // test the credentials and obtain an initial access token
+ refresher := &ClientCredentialsGrantRefresher{
+ exchanger: c.exchanger,
+ clock: c.clock,
+ }
+ grant, err = refresher.Refresh(grant)
+ if err != nil {
+ return nil, errors.Wrap(err, "authentication failed using client credentials")
+ }
+ return grant, nil
+}
+
+type ClientCredentialsGrantRefresher struct {
+ exchanger ClientCredentialsExchanger
+ clock clock.Clock
+}
+
+func NewDefaultClientCredentialsGrantRefresher(clock clock.Clock) (*ClientCredentialsGrantRefresher, error) {
+ tokenRetriever := NewTokenRetriever(&http.Client{})
+ return &ClientCredentialsGrantRefresher{
+ exchanger: tokenRetriever,
+ clock: clock,
+ }, nil
+}
+
+var _ AuthorizationGrantRefresher = &ClientCredentialsGrantRefresher{}
+
+func (g *ClientCredentialsGrantRefresher) Refresh(grant *AuthorizationGrant) (*AuthorizationGrant, error) {
+ if grant.Type != GrantTypeClientCredentials {
+ return nil, errors.New("unsupported grant type")
+ }
+
+ exchangeRequest := ClientCredentialsExchangeRequest{
+ TokenEndpoint: grant.TokenEndpoint,
+ Audience: grant.Audience,
+ ClientID: grant.ClientCredentials.ClientID,
+ ClientSecret: grant.ClientCredentials.ClientSecret,
+ Scopes: grant.Scopes,
+ }
+ tr, err := g.exchanger.ExchangeClientCredentials(exchangeRequest)
+ if err != nil {
+ return nil, errors.Wrap(err, "could not exchange client credentials")
+ }
+
+ token := convertToOAuth2Token(tr, g.clock)
+ grant = &AuthorizationGrant{
+ Type: GrantTypeClientCredentials,
+ Audience: grant.Audience,
+ ClientID: grant.ClientID,
+ ClientCredentials: grant.ClientCredentials,
+ TokenEndpoint: grant.TokenEndpoint,
+ Token: &token,
+ Scopes: grant.Scopes,
+ }
+ return grant, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/client_credentials_provider.go b/vendor/github.com/apache/pulsar-client-go/oauth2/client_credentials_provider.go
new file mode 100644
index 00000000..3eb8ba44
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/client_credentials_provider.go
@@ -0,0 +1,80 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "encoding/json"
+ "os"
+ "strings"
+)
+
+const (
+ FILE = "file://"
+ DATA = "data://"
+)
+
+type KeyFileProvider struct {
+ KeyFile string
+}
+
+type KeyFile struct {
+ Type string `json:"type"`
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret"`
+ ClientEmail string `json:"client_email"`
+ IssuerURL string `json:"issuer_url"`
+}
+
+func NewClientCredentialsProviderFromKeyFile(keyFile string) *KeyFileProvider {
+ return &KeyFileProvider{
+ KeyFile: keyFile,
+ }
+}
+
+var _ ClientCredentialsProvider = &KeyFileProvider{}
+
+func (k *KeyFileProvider) GetClientCredentials() (*KeyFile, error) {
+ var keyFile []byte
+ var err error
+ switch {
+ case strings.HasPrefix(k.KeyFile, FILE):
+ filename := strings.TrimPrefix(k.KeyFile, FILE)
+ keyFile, err = os.ReadFile(filename)
+ case strings.HasPrefix(k.KeyFile, DATA):
+ keyFile = []byte(strings.TrimPrefix(k.KeyFile, DATA))
+ case strings.HasPrefix(k.KeyFile, "data:"):
+ url, err := newDataURL(k.KeyFile)
+ if err != nil {
+ return nil, err
+ }
+ keyFile = url.Data
+ default:
+ keyFile, err = os.ReadFile(k.KeyFile)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ var v KeyFile
+ err = json.Unmarshal(keyFile, &v)
+ if err != nil {
+ return nil, err
+ }
+
+ return &v, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/clock/clock.go b/vendor/github.com/apache/pulsar-client-go/oauth2/clock/clock.go
new file mode 100644
index 00000000..f170d9af
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/clock/clock.go
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package clock
+
+import "time"
+
+// Clock allows for injecting fake or real clocks into code that
+// needs to do arbitrary things based on time.
+type Clock interface {
+ Now() time.Time
+ Since(time.Time) time.Duration
+ After(d time.Duration) <-chan time.Time
+ NewTimer(d time.Duration) Timer
+ Sleep(d time.Duration)
+ Tick(d time.Duration) <-chan time.Time
+}
+
+var _ = Clock(RealClock{})
+
+// RealClock really calls time.Now()
+type RealClock struct{}
+
+// Now returns the current time.
+func (RealClock) Now() time.Time {
+ return time.Now()
+}
+
+// Since returns time since the specified timestamp.
+func (RealClock) Since(ts time.Time) time.Duration {
+ return time.Since(ts)
+}
+
+// After is the same as time.After(d).
+func (RealClock) After(d time.Duration) <-chan time.Time {
+ return time.After(d)
+}
+
+// NewTimer is the same as time.NewTimer(d)
+func (RealClock) NewTimer(d time.Duration) Timer {
+ return &realTimer{
+ timer: time.NewTimer(d),
+ }
+}
+
+// Tick is the same as time.Tick(d)
+func (RealClock) Tick(d time.Duration) <-chan time.Time {
+ return time.Tick(d)
+}
+
+// Sleep is the same as time.Sleep(d)
+func (RealClock) Sleep(d time.Duration) {
+ time.Sleep(d)
+}
+
+// Timer allows for injecting fake or real timers into code that
+// needs to do arbitrary things based on time.
+type Timer interface {
+ C() <-chan time.Time
+ Stop() bool
+ Reset(d time.Duration) bool
+}
+
+var _ = Timer(&realTimer{})
+
+// realTimer is backed by an actual time.Timer.
+type realTimer struct {
+ timer *time.Timer
+}
+
+// C returns the underlying timer's channel.
+func (r *realTimer) C() <-chan time.Time {
+ return r.timer.C
+}
+
+// Stop calls Stop() on the underlying timer.
+func (r *realTimer) Stop() bool {
+ return r.timer.Stop()
+}
+
+// Reset calls Reset() on the underlying timer.
+func (r *realTimer) Reset(d time.Duration) bool {
+ return r.timer.Reset(d)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/config_tokenprovider.go b/vendor/github.com/apache/pulsar-client-go/oauth2/config_tokenprovider.go
new file mode 100644
index 00000000..627749fb
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/config_tokenprovider.go
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import "fmt"
+
+type configProvider interface {
+ GetTokens(identifier string) (string, string)
+ SaveTokens(identifier, accessToken, refreshToken string)
+}
+
+// ConfigBackedCachingProvider wraps a configProvider in order to conform to
+// the cachingProvider interface
+type ConfigBackedCachingProvider struct {
+ identifier string
+ config configProvider
+}
+
+// NewConfigBackedCachingProvider builds and returns a CachingTokenProvider
+// that utilizes a configProvider to cache tokens
+func NewConfigBackedCachingProvider(clientID, audience string, config configProvider) *ConfigBackedCachingProvider {
+ return &ConfigBackedCachingProvider{
+ identifier: fmt.Sprintf("%s-%s", clientID, audience),
+ config: config,
+ }
+}
+
+// GetTokens gets the tokens from the cache and returns them as a TokenResult
+func (c *ConfigBackedCachingProvider) GetTokens() (*TokenResult, error) {
+ accessToken, refreshToken := c.config.GetTokens(c.identifier)
+ return &TokenResult{
+ AccessToken: accessToken,
+ RefreshToken: refreshToken,
+ }, nil
+}
+
+// CacheTokens caches the id and refresh token from TokenResult in the
+// configProvider
+func (c *ConfigBackedCachingProvider) CacheTokens(toCache *TokenResult) error {
+ c.config.SaveTokens(c.identifier, toCache.AccessToken, toCache.RefreshToken)
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/data_url.go b/vendor/github.com/apache/pulsar-client-go/oauth2/data_url.go
new file mode 100644
index 00000000..8d711f83
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/data_url.go
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "encoding/base64"
+ "errors"
+ "regexp"
+)
+
+var errDataURLInvalid = errors.New("invalid data URL")
+
+// https://datatracker.ietf.org/doc/html/rfc2397
+var dataURLRegex = regexp.MustCompile("^data:(?P[^;,]+)?(;(?Pcharset=[^;,]+))?" +
+ "(;(?Pbase64))?,(?P.+)")
+
+type dataURL struct {
+ url string
+ Mimetype string
+ Data []byte
+}
+
+func newDataURL(url string) (*dataURL, error) {
+ if !dataURLRegex.Match([]byte(url)) {
+ return nil, errDataURLInvalid
+ }
+
+ match := dataURLRegex.FindStringSubmatch(url)
+ if len(match) != 7 {
+ return nil, errDataURLInvalid
+ }
+
+ dataURL := &dataURL{
+ url: url,
+ }
+
+ mimetype := match[dataURLRegex.SubexpIndex("mimetype")]
+ if mimetype == "" {
+ mimetype = "text/plain"
+ }
+ dataURL.Mimetype = mimetype
+
+ data := match[dataURLRegex.SubexpIndex("data")]
+ if match[dataURLRegex.SubexpIndex("base64")] == "" {
+ dataURL.Data = []byte(data)
+ } else {
+ data, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ return nil, err
+ }
+ dataURL.Data = data
+ }
+
+ return dataURL, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/device_code_flow.go b/vendor/github.com/apache/pulsar-client-go/oauth2/device_code_flow.go
new file mode 100644
index 00000000..d46148a8
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/device_code_flow.go
@@ -0,0 +1,205 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/apache/pulsar-client-go/oauth2/clock"
+
+ "github.com/pkg/errors"
+)
+
+// DeviceCodeFlow takes care of the mechanics needed for getting an access
+// token using the OAuth 2.0 "Device Code Flow"
+type DeviceCodeFlow struct {
+ options DeviceCodeFlowOptions
+ oidcWellKnownEndpoints OIDCWellKnownEndpoints
+ codeProvider DeviceCodeProvider
+ exchanger DeviceTokenExchanger
+ callback DeviceCodeCallback
+ clock clock.Clock
+}
+
+// AuthorizationCodeProvider abstracts getting an authorization code
+type DeviceCodeProvider interface {
+ GetCode(audience string, additionalScopes ...string) (*DeviceCodeResult, error)
+}
+
+// DeviceTokenExchanger abstracts exchanging for tokens
+type DeviceTokenExchanger interface {
+ ExchangeDeviceCode(ctx context.Context, req DeviceCodeExchangeRequest) (*TokenResult, error)
+ ExchangeRefreshToken(req RefreshTokenExchangeRequest) (*TokenResult, error)
+}
+
+type DeviceCodeCallback func(code *DeviceCodeResult) error
+
+type DeviceCodeFlowOptions struct {
+ IssuerEndpoint string
+ ClientID string
+ AdditionalScopes []string
+ AllowRefresh bool
+}
+
+func newDeviceCodeFlow(
+ options DeviceCodeFlowOptions,
+ oidcWellKnownEndpoints OIDCWellKnownEndpoints,
+ codeProvider DeviceCodeProvider,
+ exchanger DeviceTokenExchanger,
+ callback DeviceCodeCallback,
+ clock clock.Clock) *DeviceCodeFlow {
+ return &DeviceCodeFlow{
+ options: options,
+ oidcWellKnownEndpoints: oidcWellKnownEndpoints,
+ codeProvider: codeProvider,
+ exchanger: exchanger,
+ callback: callback,
+ clock: clock,
+ }
+}
+
+// NewDefaultDeviceCodeFlow provides an easy way to build up a default
+// device code flow with all the correct configuration. If refresh tokens should
+// be allowed pass in true for
+func NewDefaultDeviceCodeFlow(options DeviceCodeFlowOptions,
+ callback DeviceCodeCallback) (*DeviceCodeFlow, error) {
+ wellKnownEndpoints, err := GetOIDCWellKnownEndpointsFromIssuerURL(options.IssuerEndpoint)
+ if err != nil {
+ return nil, err
+ }
+
+ codeProvider := NewLocalDeviceCodeProvider(
+ LocalDeviceCodeProviderOptions{
+ ClientID: options.ClientID,
+ },
+ *wellKnownEndpoints,
+ &http.Client{},
+ )
+
+ tokenRetriever := NewTokenRetriever(&http.Client{})
+
+ return newDeviceCodeFlow(
+ options,
+ *wellKnownEndpoints,
+ codeProvider,
+ tokenRetriever,
+ callback,
+ clock.RealClock{}), nil
+}
+
+var _ Flow = &DeviceCodeFlow{}
+
+func (p *DeviceCodeFlow) Authorize(audience string) (*AuthorizationGrant, error) {
+
+ var additionalScopes []string
+ additionalScopes = append(additionalScopes, p.options.AdditionalScopes...)
+ if p.options.AllowRefresh {
+ additionalScopes = append(additionalScopes, "offline_access")
+ }
+
+ codeResult, err := p.codeProvider.GetCode(audience, additionalScopes...)
+ if err != nil {
+ return nil, err
+ }
+
+ if p.callback != nil {
+ err := p.callback(codeResult)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ exchangeRequest := DeviceCodeExchangeRequest{
+ TokenEndpoint: p.oidcWellKnownEndpoints.TokenEndpoint,
+ ClientID: p.options.ClientID,
+ DeviceCode: codeResult.DeviceCode,
+ PollInterval: time.Duration(codeResult.Interval) * time.Second,
+ }
+
+ tr, err := p.exchanger.ExchangeDeviceCode(context.Background(), exchangeRequest)
+ if err != nil {
+ return nil, errors.Wrap(err, "could not exchange code")
+ }
+
+ token := convertToOAuth2Token(tr, p.clock)
+ grant := &AuthorizationGrant{
+ Type: GrantTypeDeviceCode,
+ Audience: audience,
+ ClientID: p.options.ClientID,
+ TokenEndpoint: p.oidcWellKnownEndpoints.TokenEndpoint,
+ Token: &token,
+ Scopes: additionalScopes,
+ }
+ return grant, nil
+}
+
+type DeviceAuthorizationGrantRefresher struct {
+ exchanger DeviceTokenExchanger
+ clock clock.Clock
+}
+
+// NewDefaultDeviceAuthorizationGrantRefresher constructs a grant refresher based on the result
+// of the device authorization flow.
+func NewDefaultDeviceAuthorizationGrantRefresher(clock clock.Clock) (*DeviceAuthorizationGrantRefresher, error) {
+ tokenRetriever := NewTokenRetriever(&http.Client{})
+ return &DeviceAuthorizationGrantRefresher{
+ exchanger: tokenRetriever,
+ clock: clock,
+ }, nil
+}
+
+var _ AuthorizationGrantRefresher = &DeviceAuthorizationGrantRefresher{}
+
+func (g *DeviceAuthorizationGrantRefresher) Refresh(grant *AuthorizationGrant) (*AuthorizationGrant, error) {
+ if grant.Type != GrantTypeDeviceCode {
+ return nil, errors.New("unsupported grant type")
+ }
+ if grant.Token == nil || grant.Token.RefreshToken == "" {
+ return nil, fmt.Errorf("the authorization grant has expired (no refresh token); please re-login")
+ }
+
+ exchangeRequest := RefreshTokenExchangeRequest{
+ TokenEndpoint: grant.TokenEndpoint,
+ ClientID: grant.ClientID,
+ RefreshToken: grant.Token.RefreshToken,
+ }
+ tr, err := g.exchanger.ExchangeRefreshToken(exchangeRequest)
+ if err != nil {
+ return nil, errors.Wrap(err, "could not exchange refresh token")
+ }
+
+ // RFC 6749 Section 1.5 - token exchange MAY issue a new refresh token (otherwise the result is blank).
+ // also see: https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13#section-4.12
+ if tr.RefreshToken == "" {
+ tr.RefreshToken = grant.Token.RefreshToken
+ }
+
+ token := convertToOAuth2Token(tr, g.clock)
+ grant = &AuthorizationGrant{
+ Type: GrantTypeDeviceCode,
+ Audience: grant.Audience,
+ ClientID: grant.ClientID,
+ Token: &token,
+ TokenEndpoint: grant.TokenEndpoint,
+ Scopes: grant.Scopes,
+ }
+ return grant, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/device_code_provider.go b/vendor/github.com/apache/pulsar-client-go/oauth2/device_code_provider.go
new file mode 100644
index 00000000..77e1eb90
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/device_code_provider.go
@@ -0,0 +1,137 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+)
+
+// DeviceCodeProvider holds the information needed to easily get a
+// device code locally.
+type LocalDeviceCodeProvider struct {
+ options LocalDeviceCodeProviderOptions
+ oidcWellKnownEndpoints OIDCWellKnownEndpoints
+ transport HTTPAuthTransport
+}
+
+type DeviceCodeRequest struct {
+ ClientID string
+ Scopes []string
+ Audience string
+}
+
+// DeviceCodeResult holds the device code gotten from the device code URL.
+type DeviceCodeResult struct {
+ DeviceCode string `json:"device_code"`
+ UserCode string `json:"user_code"`
+ VerificationURI string `json:"verification_uri"`
+ VerificationURIComplete string `json:"verification_uri_complete"`
+ ExpiresIn int `json:"expires_in"`
+ Interval int `json:"interval"`
+}
+
+type LocalDeviceCodeProviderOptions struct {
+ ClientID string
+}
+
+// NewLocalDeviceCodeProvider allows for the easy setup of LocalDeviceCodeProvider
+func NewLocalDeviceCodeProvider(
+ options LocalDeviceCodeProviderOptions,
+ oidcWellKnownEndpoints OIDCWellKnownEndpoints,
+ authTransport HTTPAuthTransport) *LocalDeviceCodeProvider {
+ return &LocalDeviceCodeProvider{
+ options,
+ oidcWellKnownEndpoints,
+ authTransport,
+ }
+}
+
+// GetCode obtains a new device code. Additional scopes
+// beyond openid and email can be sent by passing in arguments for
+// .
+func (cp *LocalDeviceCodeProvider) GetCode(audience string, additionalScopes ...string) (*DeviceCodeResult, error) {
+ request, err := cp.newDeviceCodeRequest(&DeviceCodeRequest{
+ ClientID: cp.options.ClientID,
+ Scopes: append([]string{"openid", "email"}, additionalScopes...),
+ Audience: audience,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := cp.transport.Do(request)
+ if err != nil {
+ return nil, err
+ }
+
+ dcr, err := cp.handleDeviceCodeResponse(response)
+ if err != nil {
+ return nil, err
+ }
+
+ return dcr, nil
+}
+
+// newDeviceCodeRequest builds a new DeviceCodeRequest wrapped in an
+// http.Request
+func (cp *LocalDeviceCodeProvider) newDeviceCodeRequest(
+ req *DeviceCodeRequest) (*http.Request, error) {
+ uv := url.Values{}
+ uv.Set("client_id", req.ClientID)
+ if len(req.Scopes) > 0 {
+ uv.Set("scope", strings.Join(req.Scopes, " "))
+ }
+ if req.Audience != "" {
+ uv.Set("audience", req.Audience)
+ }
+ euv := uv.Encode()
+
+ request, err := http.NewRequest("POST",
+ cp.oidcWellKnownEndpoints.DeviceAuthorizationEndpoint,
+ strings.NewReader(euv),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ request.Header.Add("Content-Length", strconv.Itoa(len(euv)))
+
+ return request, nil
+}
+
+func (cp *LocalDeviceCodeProvider) handleDeviceCodeResponse(resp *http.Response) (*DeviceCodeResult, error) {
+ if resp.StatusCode < 200 || resp.StatusCode >= 300 {
+ return nil, fmt.Errorf("a non-success status code was received: %d", resp.StatusCode)
+ }
+
+ defer resp.Body.Close()
+
+ dcr := DeviceCodeResult{}
+ err := json.NewDecoder(resp.Body).Decode(&dcr)
+ if err != nil {
+ return nil, err
+ }
+
+ return &dcr, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/oidc_endpoint_provider.go b/vendor/github.com/apache/pulsar-client-go/oauth2/oidc_endpoint_provider.go
new file mode 100644
index 00000000..32986b73
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/oidc_endpoint_provider.go
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "encoding/json"
+ "net/http"
+ "net/url"
+ "path"
+
+ "github.com/pkg/errors"
+)
+
+// OIDCWellKnownEndpoints holds the well known OIDC endpoints
+type OIDCWellKnownEndpoints struct {
+ AuthorizationEndpoint string `json:"authorization_endpoint"`
+ TokenEndpoint string `json:"token_endpoint"`
+ DeviceAuthorizationEndpoint string `json:"device_authorization_endpoint"`
+}
+
+// GetOIDCWellKnownEndpointsFromIssuerURL gets the well known endpoints for the
+// passed in issuer url
+func GetOIDCWellKnownEndpointsFromIssuerURL(issuerURL string) (*OIDCWellKnownEndpoints, error) {
+ u, err := url.Parse(issuerURL)
+ if err != nil {
+ return nil, errors.Wrap(err, "could not parse issuer url to build well known endpoints")
+ }
+ u.Path = path.Join(u.Path, ".well-known/openid-configuration")
+
+ r, err := http.Get(u.String())
+ if err != nil {
+ return nil, errors.Wrapf(err, "could not get well known endpoints from url %s", u.String())
+ }
+ defer r.Body.Close()
+
+ var wkEndpoints OIDCWellKnownEndpoints
+ err = json.NewDecoder(r.Body).Decode(&wkEndpoints)
+ if err != nil {
+ return nil, errors.Wrap(err, "could not decode json body when getting well known endpoints")
+ }
+
+ return &wkEndpoints, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/store/keyring.go b/vendor/github.com/apache/pulsar-client-go/oauth2/store/keyring.go
new file mode 100644
index 00000000..8a024f59
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/store/keyring.go
@@ -0,0 +1,194 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package store
+
+import (
+ "crypto/sha1"
+ "encoding/json"
+ "fmt"
+ "sync"
+
+ "github.com/99designs/keyring"
+ "github.com/apache/pulsar-client-go/oauth2"
+ "github.com/apache/pulsar-client-go/oauth2/clock"
+)
+
+type KeyringStore struct {
+ kr keyring.Keyring
+ clock clock.Clock
+ lock sync.Mutex
+}
+
+// storedItem represents an item stored in the keyring
+type storedItem struct {
+ Audience string
+ UserName string
+ Grant oauth2.AuthorizationGrant
+}
+
+// NewKeyringStore creates a store based on a keyring.
+func NewKeyringStore(kr keyring.Keyring) (*KeyringStore, error) {
+ return &KeyringStore{
+ kr: kr,
+ clock: clock.RealClock{},
+ }, nil
+}
+
+var _ Store = &KeyringStore{}
+
+func (f *KeyringStore) SaveGrant(audience string, grant oauth2.AuthorizationGrant) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ var err error
+ var userName string
+ switch grant.Type {
+ case oauth2.GrantTypeClientCredentials:
+ if grant.ClientCredentials == nil {
+ return ErrUnsupportedAuthData
+ }
+ userName = grant.ClientCredentials.ClientEmail
+ case oauth2.GrantTypeDeviceCode:
+ if grant.Token == nil {
+ return ErrUnsupportedAuthData
+ }
+ userName, err = oauth2.ExtractUserName(*grant.Token)
+ if err != nil {
+ return err
+ }
+ default:
+ return ErrUnsupportedAuthData
+ }
+ item := storedItem{
+ Audience: audience,
+ UserName: userName,
+ Grant: grant,
+ }
+ err = f.setItem(item)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (f *KeyringStore) LoadGrant(audience string) (*oauth2.AuthorizationGrant, error) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ item, err := f.getItem(audience)
+ if err != nil {
+ if err == keyring.ErrKeyNotFound {
+ return nil, ErrNoAuthenticationData
+ }
+ return nil, err
+ }
+ switch item.Grant.Type {
+ case oauth2.GrantTypeClientCredentials:
+ if item.Grant.ClientCredentials == nil {
+ return nil, ErrUnsupportedAuthData
+ }
+ case oauth2.GrantTypeDeviceCode:
+ if item.Grant.Token == nil {
+ return nil, ErrUnsupportedAuthData
+ }
+ default:
+ return nil, ErrUnsupportedAuthData
+ }
+ return &item.Grant, nil
+}
+
+func (f *KeyringStore) WhoAmI(audience string) (string, error) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ key := hashKeyringKey(audience)
+ authItem, err := f.kr.Get(key)
+ if err != nil {
+ if err == keyring.ErrKeyNotFound {
+ return "", ErrNoAuthenticationData
+ }
+ return "", fmt.Errorf("unable to get information from the keyring: %v", err)
+ }
+ return authItem.Label, nil
+}
+
+func (f *KeyringStore) Logout() error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ var err error
+ keys, err := f.kr.Keys()
+ if err != nil {
+ return fmt.Errorf("unable to get information from the keyring: %v", err)
+ }
+ for _, key := range keys {
+ err = f.kr.Remove(key)
+ }
+ if err != nil {
+ return fmt.Errorf("unable to update the keyring: %v", err)
+ }
+ return nil
+}
+
+func (f *KeyringStore) getItem(audience string) (storedItem, error) {
+ key := hashKeyringKey(audience)
+ i, err := f.kr.Get(key)
+ if err != nil {
+ return storedItem{}, err
+ }
+ var grant oauth2.AuthorizationGrant
+ err = json.Unmarshal(i.Data, &grant)
+ if err != nil {
+ // the grant appears to be invalid
+ return storedItem{}, ErrUnsupportedAuthData
+ }
+ return storedItem{
+ Audience: audience,
+ UserName: i.Label,
+ Grant: grant,
+ }, nil
+}
+
+func (f *KeyringStore) setItem(item storedItem) error {
+ key := hashKeyringKey(item.Audience)
+ data, err := json.Marshal(item.Grant)
+ if err != nil {
+ return err
+ }
+ i := keyring.Item{
+ Key: key,
+ Data: data,
+ Label: item.UserName,
+ Description: "authorization grant",
+ KeychainNotTrustApplication: false,
+ KeychainNotSynchronizable: false,
+ }
+ err = f.kr.Set(i)
+ if err != nil {
+ return fmt.Errorf("unable to update the keyring: %v", err)
+ }
+ return nil
+}
+
+// hashKeyringKey creates a safe key based on the given string
+func hashKeyringKey(s string) string {
+ h := sha1.New()
+ h.Write([]byte(s))
+ bs := h.Sum(nil)
+ return fmt.Sprintf("%x", bs)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/store/memory.go b/vendor/github.com/apache/pulsar-client-go/oauth2/store/memory.go
new file mode 100644
index 00000000..07c75947
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/store/memory.go
@@ -0,0 +1,87 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package store
+
+import (
+ "sync"
+
+ "github.com/apache/pulsar-client-go/oauth2"
+ "github.com/apache/pulsar-client-go/oauth2/clock"
+)
+
+type MemoryStore struct {
+ clock clock.Clock
+ lock sync.Mutex
+ grants map[string]*oauth2.AuthorizationGrant
+}
+
+func NewMemoryStore() Store {
+ return &MemoryStore{
+ clock: clock.RealClock{},
+ grants: make(map[string]*oauth2.AuthorizationGrant),
+ }
+}
+
+var _ Store = &MemoryStore{}
+
+func (f *MemoryStore) SaveGrant(audience string, grant oauth2.AuthorizationGrant) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ f.grants[audience] = &grant
+ return nil
+}
+
+func (f *MemoryStore) LoadGrant(audience string) (*oauth2.AuthorizationGrant, error) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ grant, ok := f.grants[audience]
+ if !ok {
+ return nil, ErrNoAuthenticationData
+ }
+ return grant, nil
+}
+
+func (f *MemoryStore) WhoAmI(audience string) (string, error) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ grant, ok := f.grants[audience]
+ if !ok {
+ return "", ErrNoAuthenticationData
+ }
+ switch grant.Type {
+ case oauth2.GrantTypeClientCredentials:
+ if grant.ClientCredentials == nil {
+ return "", ErrUnsupportedAuthData
+ }
+ return grant.ClientCredentials.ClientEmail, nil
+ case oauth2.GrantTypeDeviceCode:
+ if grant.Token == nil {
+ return "", ErrUnsupportedAuthData
+ }
+ return oauth2.ExtractUserName(*grant.Token)
+ default:
+ return "", ErrUnsupportedAuthData
+ }
+}
+
+func (f *MemoryStore) Logout() error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ f.grants = map[string]*oauth2.AuthorizationGrant{}
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/oauth2/store/store.go b/vendor/github.com/apache/pulsar-client-go/oauth2/store/store.go
new file mode 100644
index 00000000..55d4c9ec
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/oauth2/store/store.go
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package store
+
+import (
+ "errors"
+
+ "github.com/apache/pulsar-client-go/oauth2"
+)
+
+// ErrNoAuthenticationData indicates that stored authentication data is not available
+var ErrNoAuthenticationData = errors.New("authentication data is not available")
+
+// ErrUnsupportedAuthData ndicates that stored authentication data is unusable
+var ErrUnsupportedAuthData = errors.New("authentication data is not usable")
+
+// Store is responsible for persisting authorization grants
+type Store interface {
+ // SaveGrant stores an authorization grant for a given audience
+ SaveGrant(audience string, grant oauth2.AuthorizationGrant) error
+
+ // LoadGrant loads an authorization grant for a given audience
+ LoadGrant(audience string) (*oauth2.AuthorizationGrant, error)
+
+ // WhoAmI returns the current user name (or an error if nobody is logged in)
+ WhoAmI(audience string) (string, error)
+
+ // Logout deletes all stored credentials
+ Logout() error
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/ack_grouping_tracker.go b/vendor/github.com/apache/pulsar-client-go/pulsar/ack_grouping_tracker.go
new file mode 100644
index 00000000..dd051868
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/ack_grouping_tracker.go
@@ -0,0 +1,266 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "sync"
+ "sync/atomic"
+ "time"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/bits-and-blooms/bitset"
+)
+
+type ackGroupingTracker interface {
+ add(id MessageID)
+
+ addCumulative(id MessageID)
+
+ isDuplicate(id MessageID) bool
+
+ flush()
+
+ flushAndClean()
+
+ close()
+}
+
+func newAckGroupingTracker(options *AckGroupingOptions,
+ ackIndividual func(id MessageID),
+ ackCumulative func(id MessageID),
+ ackList func(ids []*pb.MessageIdData)) ackGroupingTracker {
+ if options == nil {
+ options = &AckGroupingOptions{
+ MaxSize: 1000,
+ MaxTime: 100 * time.Millisecond,
+ }
+ }
+
+ if options.MaxSize <= 1 {
+ return &immediateAckGroupingTracker{
+ ackIndividual: ackIndividual,
+ ackCumulative: ackCumulative,
+ }
+ }
+
+ t := &timedAckGroupingTracker{
+ maxNumAcks: int(options.MaxSize),
+ ackCumulative: ackCumulative,
+ ackList: ackList,
+ pendingAcks: make(map[[2]uint64]*bitset.BitSet),
+ lastCumulativeAck: EarliestMessageID(),
+ }
+
+ if options.MaxTime > 0 {
+ t.ticker = time.NewTicker(options.MaxTime)
+ t.exitCh = make(chan struct{})
+ go func() {
+ for {
+ select {
+ case <-t.exitCh:
+ return
+ case <-t.ticker.C:
+ t.flush()
+ }
+ }
+ }()
+ }
+
+ return t
+}
+
+type immediateAckGroupingTracker struct {
+ ackIndividual func(id MessageID)
+ ackCumulative func(id MessageID)
+}
+
+func (i *immediateAckGroupingTracker) add(id MessageID) {
+ i.ackIndividual(id)
+}
+
+func (i *immediateAckGroupingTracker) addCumulative(id MessageID) {
+ i.ackCumulative(id)
+}
+
+func (i *immediateAckGroupingTracker) isDuplicate(id MessageID) bool {
+ return false
+}
+
+func (i *immediateAckGroupingTracker) flush() {
+}
+
+func (i *immediateAckGroupingTracker) flushAndClean() {
+}
+
+func (i *immediateAckGroupingTracker) close() {
+}
+
+type timedAckGroupingTracker struct {
+ sync.RWMutex
+
+ maxNumAcks int
+ ackCumulative func(id MessageID)
+ ackList func(ids []*pb.MessageIdData)
+ ticker *time.Ticker
+
+ // Key is the pair of the ledger id and the entry id,
+ // Value is the bit set that represents which messages are acknowledged if the entry stores a batch.
+ // The bit 1 represents the message has been acknowledged, i.e. the bits "111" represents all messages
+ // in the batch whose batch size is 3 are not acknowledged.
+ // After the 1st message (i.e. batch index is 0) is acknowledged, the bits will become "011".
+ // Value is nil if the entry represents a single message.
+ pendingAcks map[[2]uint64]*bitset.BitSet
+
+ lastCumulativeAck MessageID
+ cumulativeAckRequired int32
+
+ exitCh chan struct{}
+}
+
+func (t *timedAckGroupingTracker) add(id MessageID) {
+ if acks := t.tryAddIndividual(id); acks != nil {
+ t.flushIndividual(acks)
+ }
+}
+
+func (t *timedAckGroupingTracker) tryAddIndividual(id MessageID) map[[2]uint64]*bitset.BitSet {
+ t.Lock()
+ defer t.Unlock()
+ key := [2]uint64{uint64(id.LedgerID()), uint64(id.EntryID())}
+
+ batchIdx := id.BatchIdx()
+ batchSize := id.BatchSize()
+
+ if batchIdx >= 0 && batchSize > 0 {
+ bs, found := t.pendingAcks[key]
+ if !found {
+ if batchSize > 1 {
+ bs = bitset.New(uint(batchSize))
+ for i := uint(0); i < uint(batchSize); i++ {
+ bs.Set(i)
+ }
+ }
+ t.pendingAcks[key] = bs
+ }
+ if bs != nil {
+ bs.Clear(uint(batchIdx))
+ }
+ } else {
+ t.pendingAcks[key] = nil
+ }
+
+ if len(t.pendingAcks) >= t.maxNumAcks {
+ pendingAcks := t.pendingAcks
+ t.pendingAcks = make(map[[2]uint64]*bitset.BitSet)
+ return pendingAcks
+ }
+ return nil
+}
+
+func (t *timedAckGroupingTracker) addCumulative(id MessageID) {
+ if t.tryUpdateCumulative(id) && t.ticker == nil {
+ t.ackCumulative(id)
+ }
+}
+
+func (t *timedAckGroupingTracker) tryUpdateCumulative(id MessageID) bool {
+ t.Lock()
+ defer t.Unlock()
+ if messageIDCompare(t.lastCumulativeAck, id) < 0 {
+ t.lastCumulativeAck = id
+ atomic.StoreInt32(&t.cumulativeAckRequired, 1)
+ return true
+ }
+ return false
+}
+
+func (t *timedAckGroupingTracker) isDuplicate(id MessageID) bool {
+ t.RLock()
+ defer t.RUnlock()
+ if messageIDCompare(t.lastCumulativeAck, id) >= 0 {
+ return true
+ }
+ key := [2]uint64{uint64(id.LedgerID()), uint64(id.EntryID())}
+ if bs, found := t.pendingAcks[key]; found {
+ if bs == nil {
+ return true
+ }
+ if !bs.Test(uint(id.BatchIdx())) {
+ return true
+ }
+ }
+ return false
+}
+
+func (t *timedAckGroupingTracker) flush() {
+ if acks := t.clearPendingAcks(); len(acks) > 0 {
+ t.flushIndividual(acks)
+ }
+ if atomic.CompareAndSwapInt32(&t.cumulativeAckRequired, 1, 0) {
+ t.RLock()
+ id := t.lastCumulativeAck
+ t.RUnlock()
+ t.ackCumulative(id)
+ }
+}
+
+func (t *timedAckGroupingTracker) flushAndClean() {
+ if acks := t.clearPendingAcks(); len(acks) > 0 {
+ t.flushIndividual(acks)
+ }
+ if atomic.CompareAndSwapInt32(&t.cumulativeAckRequired, 1, 0) {
+ t.Lock()
+ id := t.lastCumulativeAck
+ t.lastCumulativeAck = EarliestMessageID()
+ t.Unlock()
+ t.ackCumulative(id)
+ }
+}
+
+func (t *timedAckGroupingTracker) clearPendingAcks() map[[2]uint64]*bitset.BitSet {
+ t.Lock()
+ defer t.Unlock()
+ pendingAcks := t.pendingAcks
+ t.pendingAcks = make(map[[2]uint64]*bitset.BitSet)
+ return pendingAcks
+}
+
+func (t *timedAckGroupingTracker) close() {
+ t.flushAndClean()
+ if t.exitCh != nil {
+ close(t.exitCh)
+ }
+}
+
+func (t *timedAckGroupingTracker) flushIndividual(pendingAcks map[[2]uint64]*bitset.BitSet) {
+ msgIDs := make([]*pb.MessageIdData, 0, len(pendingAcks))
+ for k, v := range pendingAcks {
+ ledgerID := k[0]
+ entryID := k[1]
+ msgID := &pb.MessageIdData{LedgerId: &ledgerID, EntryId: &entryID}
+ if v != nil && !v.None() {
+ bytes := v.Bytes()
+ msgID.AckSet = make([]int64, len(bytes))
+ for i := 0; i < len(bytes); i++ {
+ msgID.AckSet[i] = int64(bytes[i])
+ }
+ }
+ msgIDs = append(msgIDs, msgID)
+ }
+ t.ackList(msgIDs)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/auth/athenz.go b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/athenz.go
new file mode 100644
index 00000000..35b3cc4e
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/athenz.go
@@ -0,0 +1,268 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+ "crypto/tls"
+ "encoding/base64"
+ "errors"
+ "net/http"
+ "os"
+ "regexp"
+ "strings"
+ "time"
+
+ zms "github.com/AthenZ/athenz/libs/go/zmssvctoken"
+ zts "github.com/AthenZ/athenz/libs/go/ztsroletoken"
+)
+
+const (
+ minExpire = 2 * time.Hour
+ maxExpire = 24 * time.Hour
+ defaultKeyID = "0"
+ defaultRoleHeader = "Athenz-Role-Auth"
+)
+
+type athenzAuthProvider struct {
+ providerDomain string
+ tenantDomain string
+ tenantService string
+ privateKey string
+ keyID string
+ x509CertChain string
+ caCert string
+ principalHeader string
+ roleHeader string
+ ztsURL string
+ tokenBuilder zms.TokenBuilder
+ roleToken zts.RoleToken
+ zmsNewTokenBuilder func(domain, name string, privateKeyPEM []byte, keyVersion string) (zms.TokenBuilder, error)
+ ztsNewRoleToken func(tok zms.Token, domain string, opts zts.RoleTokenOptions) zts.RoleToken
+ ztsNewRoleTokenFromCert func(certFile, keyFile, domain string, opts zts.RoleTokenOptions) zts.RoleToken
+
+ T http.RoundTripper
+}
+
+type parsedURI struct {
+ Scheme string
+ MediaTypeAndEncodingType string
+ Data string
+ Path string
+}
+
+func NewAuthenticationAthenzWithParams(params map[string]string) (Provider, error) {
+ return NewAuthenticationAthenz(
+ params["providerDomain"],
+ params["tenantDomain"],
+ params["tenantService"],
+ params["privateKey"],
+ params["keyId"],
+ params["x509CertChain"],
+ params["caCert"],
+ params["principalHeader"],
+ params["roleHeader"],
+ params["ztsUrl"],
+ ), nil
+}
+
+func NewAuthenticationAthenz(
+ providerDomain string,
+ tenantDomain string,
+ tenantService string,
+ privateKey string,
+ keyID string,
+ x509CertChain string,
+ caCert string,
+ principalHeader string,
+ roleHeader string,
+ ztsURL string) Provider {
+ fixedKeyID := defaultKeyID
+ if keyID != "" {
+ fixedKeyID = keyID
+ }
+
+ fixedRoleHeader := defaultRoleHeader
+ if roleHeader != "" {
+ fixedRoleHeader = roleHeader
+ }
+
+ ztsNewRoleToken := func(tok zms.Token, domain string, opts zts.RoleTokenOptions) zts.RoleToken {
+ return zts.RoleToken(zts.NewRoleToken(tok, domain, opts))
+ }
+
+ ztsNewRoleTokenFromCert := func(certFile, keyFile, domain string, opts zts.RoleTokenOptions) zts.RoleToken {
+ return zts.RoleToken(zts.NewRoleTokenFromCert(certFile, keyFile, domain, opts))
+ }
+
+ return &athenzAuthProvider{
+ providerDomain: providerDomain,
+ tenantDomain: tenantDomain,
+ tenantService: tenantService,
+ privateKey: privateKey,
+ keyID: fixedKeyID,
+ x509CertChain: x509CertChain,
+ caCert: caCert,
+ principalHeader: principalHeader,
+ roleHeader: fixedRoleHeader,
+ ztsURL: strings.TrimSuffix(ztsURL, "/"),
+ zmsNewTokenBuilder: zms.NewTokenBuilder,
+ ztsNewRoleToken: ztsNewRoleToken,
+ ztsNewRoleTokenFromCert: ztsNewRoleTokenFromCert,
+ }
+}
+
+func (p *athenzAuthProvider) Init() error {
+ if p.providerDomain == "" || p.privateKey == "" || p.ztsURL == "" {
+ return errors.New("missing required parameters")
+ }
+
+ var roleToken zts.RoleToken
+ opts := zts.RoleTokenOptions{
+ BaseZTSURL: p.ztsURL + "/zts/v1",
+ MinExpire: minExpire,
+ MaxExpire: maxExpire,
+ AuthHeader: p.principalHeader,
+ }
+
+ if p.x509CertChain != "" {
+ // use Copper Argos
+ certURISt := parseURI(p.x509CertChain)
+ keyURISt := parseURI(p.privateKey)
+
+ if certURISt.Scheme != "file" || keyURISt.Scheme != "file" {
+ return errors.New("x509CertChain and privateKey must be specified as file paths")
+ }
+
+ if p.caCert != "" {
+ caCertData, err := loadPEM(p.caCert)
+ if err != nil {
+ return err
+ }
+ opts.CACert = caCertData
+ }
+
+ roleToken = p.ztsNewRoleTokenFromCert(certURISt.Path, keyURISt.Path, p.providerDomain, opts)
+ } else {
+ if p.tenantDomain == "" || p.tenantService == "" {
+ return errors.New("missing required parameters")
+ }
+
+ keyData, err := loadPEM(p.privateKey)
+ if err != nil {
+ return err
+ }
+
+ tb, err := p.zmsNewTokenBuilder(p.tenantDomain, p.tenantService, keyData, p.keyID)
+ if err != nil {
+ return err
+ }
+ p.tokenBuilder = tb
+
+ roleToken = p.ztsNewRoleToken(p.tokenBuilder.Token(), p.providerDomain, opts)
+ }
+
+ p.roleToken = roleToken
+ return nil
+}
+
+func (p *athenzAuthProvider) Name() string {
+ return "athenz"
+}
+
+func (p *athenzAuthProvider) GetTLSCertificate() (*tls.Certificate, error) {
+ return nil, nil
+}
+
+func (p *athenzAuthProvider) GetData() ([]byte, error) {
+ tok, err := p.roleToken.RoleTokenValue()
+ if err != nil {
+ return nil, err
+ }
+
+ return []byte(tok), nil
+}
+
+func (p *athenzAuthProvider) Close() error {
+ return nil
+}
+
+func parseURI(uri string) parsedURI {
+ var uriSt parsedURI
+ // scheme mediatype[;base64] path file
+ const expression = `^(?:([^:/?#]+):)(?:([;/\\\-\w]*),)?(?:/{0,2}((?:[^?#/]*/)*))?([^?#]*)`
+
+ // when expression cannot be parsed, then panics
+ re := regexp.MustCompile(expression)
+ if re.MatchString(uri) {
+ groups := re.FindStringSubmatch(uri)
+ uriSt.Scheme = groups[1]
+ uriSt.MediaTypeAndEncodingType = groups[2]
+ uriSt.Data = groups[4]
+ uriSt.Path = groups[3] + groups[4]
+ } else {
+ // consider a file path specified instead of a URI
+ uriSt.Scheme = "file"
+ uriSt.Path = uri
+ }
+
+ return uriSt
+}
+
+func loadPEM(uri string) ([]byte, error) {
+ uriSt := parseURI(uri)
+ var pemData []byte
+
+ if uriSt.Scheme == "data" {
+ if uriSt.MediaTypeAndEncodingType != "application/x-pem-file;base64" {
+ return nil, errors.New("Unsupported mediaType or encodingType: " + uriSt.MediaTypeAndEncodingType)
+ }
+ pem, err := base64.StdEncoding.DecodeString(uriSt.Data)
+ if err != nil {
+ return nil, err
+ }
+ pemData = pem
+ } else if uriSt.Scheme == "file" {
+ pem, err := os.ReadFile(uriSt.Path)
+ if err != nil {
+ return nil, err
+ }
+ pemData = pem
+ } else {
+ return nil, errors.New("Unsupported URI Scheme: " + uriSt.Scheme)
+ }
+
+ return pemData, nil
+}
+
+func (p *athenzAuthProvider) RoundTrip(req *http.Request) (*http.Response, error) {
+ tok, err := p.roleToken.RoleTokenValue()
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Add(p.roleHeader, tok)
+ return p.T.RoundTrip(req)
+}
+
+func (p *athenzAuthProvider) Transport() http.RoundTripper {
+ return p.T
+}
+
+func (p *athenzAuthProvider) WithTransport(tripper http.RoundTripper) error {
+ p.T = tripper
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/auth/basic.go b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/basic.go
new file mode 100644
index 00000000..58a87f51
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/basic.go
@@ -0,0 +1,84 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+ "crypto/tls"
+ "encoding/base64"
+ "errors"
+ "net/http"
+)
+
+type basicAuthProvider struct {
+ rt http.RoundTripper
+ commandAuthToken []byte
+ httpAuthToken string
+}
+
+func NewAuthenticationBasic(username, password string) (Provider, error) {
+ if username == "" {
+ return nil, errors.New("username cannot be empty")
+ }
+ if password == "" {
+ return nil, errors.New("password cannot be empty")
+ }
+
+ commandAuthToken := []byte(username + ":" + password)
+ return &basicAuthProvider{
+ commandAuthToken: commandAuthToken,
+ httpAuthToken: "Basic " + base64.StdEncoding.EncodeToString(commandAuthToken),
+ }, nil
+}
+
+func NewAuthenticationBasicWithParams(params map[string]string) (Provider, error) {
+ return NewAuthenticationBasic(params["username"], params["password"])
+}
+
+func (b *basicAuthProvider) Init() error {
+ return nil
+}
+
+func (b *basicAuthProvider) Name() string {
+ return "basic"
+}
+
+func (b *basicAuthProvider) GetTLSCertificate() (*tls.Certificate, error) {
+ return nil, nil
+}
+
+func (b *basicAuthProvider) GetData() ([]byte, error) {
+ return b.commandAuthToken, nil
+}
+
+func (b *basicAuthProvider) Close() error {
+ return nil
+}
+
+func (b *basicAuthProvider) RoundTrip(req *http.Request) (*http.Response, error) {
+ req.Header.Add("Authorization", b.httpAuthToken)
+ return b.rt.RoundTrip(req)
+}
+
+func (b *basicAuthProvider) Transport() http.RoundTripper {
+ return b.rt
+}
+
+func (b *basicAuthProvider) WithTransport(tr http.RoundTripper) error {
+ b.rt = tr
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/auth/disabled.go b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/disabled.go
new file mode 100644
index 00000000..0389a39b
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/disabled.go
@@ -0,0 +1,62 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+ "crypto/tls"
+ "net/http"
+)
+
+type disabled struct{}
+
+// NewAuthDisabled return a interface of Provider
+func NewAuthDisabled() Provider {
+ return &disabled{}
+}
+
+func (disabled) Init() error {
+ return nil
+}
+
+func (disabled) GetData() ([]byte, error) {
+ return nil, nil
+}
+
+func (disabled) Name() string {
+ return ""
+}
+
+func (disabled) GetTLSCertificate() (*tls.Certificate, error) {
+ return nil, nil
+}
+
+func (disabled) Close() error {
+ return nil
+}
+
+func (d disabled) RoundTrip(req *http.Request) (*http.Response, error) {
+ return nil, nil
+}
+
+func (d disabled) Transport() http.RoundTripper {
+ return nil
+}
+
+func (d disabled) WithTransport(tripper http.RoundTripper) error {
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/auth/oauth2.go b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/oauth2.go
new file mode 100644
index 00000000..e162e4ed
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/oauth2.go
@@ -0,0 +1,205 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+ "crypto/tls"
+ "fmt"
+ "net/http"
+ "strings"
+
+ xoauth2 "golang.org/x/oauth2"
+
+ "github.com/apache/pulsar-client-go/oauth2"
+ "github.com/apache/pulsar-client-go/oauth2/cache"
+ "github.com/apache/pulsar-client-go/oauth2/clock"
+ "github.com/apache/pulsar-client-go/oauth2/store"
+)
+
+const (
+ ConfigParamType = "type"
+ ConfigParamTypeClientCredentials = "client_credentials"
+ ConfigParamIssuerURL = "issuerUrl"
+ ConfigParamAudience = "audience"
+ ConfigParamScope = "scope"
+ ConfigParamKeyFile = "privateKey"
+ ConfigParamClientID = "clientId"
+)
+
+type oauth2AuthProvider struct {
+ clock clock.Clock
+ issuer oauth2.Issuer
+ store store.Store
+ source cache.CachingTokenSource
+ defaultTransport http.RoundTripper
+ tokenTransport *transport
+}
+
+// NewAuthenticationOAuth2WithParams return a interface of Provider with string map.
+func NewAuthenticationOAuth2WithParams(params map[string]string) (Provider, error) {
+ issuer := oauth2.Issuer{
+ IssuerEndpoint: params[ConfigParamIssuerURL],
+ ClientID: params[ConfigParamClientID],
+ Audience: params[ConfigParamAudience],
+ }
+
+ // initialize a store of authorization grants
+ st := store.NewMemoryStore()
+ switch params[ConfigParamType] {
+ case ConfigParamTypeClientCredentials:
+ flow, err := oauth2.NewDefaultClientCredentialsFlow(oauth2.ClientCredentialsFlowOptions{
+ KeyFile: params[ConfigParamKeyFile],
+ AdditionalScopes: strings.Split(params[ConfigParamScope], " "),
+ })
+ if err != nil {
+ return nil, err
+ }
+ grant, err := flow.Authorize(issuer.Audience)
+ if err != nil {
+ return nil, err
+ }
+ err = st.SaveGrant(issuer.Audience, *grant)
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, fmt.Errorf("unsupported authentication type: %s", params[ConfigParamType])
+ }
+
+ return NewAuthenticationOAuth2(issuer, st), nil
+}
+
+func NewAuthenticationOAuth2(
+ issuer oauth2.Issuer,
+ store store.Store) Provider {
+
+ return &oauth2AuthProvider{
+ clock: clock.RealClock{},
+ issuer: issuer,
+ store: store,
+ }
+}
+
+func (p *oauth2AuthProvider) Init() error {
+ grant, err := p.store.LoadGrant(p.issuer.Audience)
+ if err != nil {
+ if err == store.ErrNoAuthenticationData {
+ return nil
+ }
+ return err
+ }
+ refresher, err := p.getRefresher(grant.Type)
+ if err != nil {
+ return err
+ }
+
+ source, err := cache.NewDefaultTokenCache(p.store, p.issuer.Audience, refresher)
+ if err != nil {
+ return err
+ }
+ p.source = source
+ return nil
+}
+
+func (p *oauth2AuthProvider) Name() string {
+ return "token"
+}
+
+func (p *oauth2AuthProvider) GetTLSCertificate() (*tls.Certificate, error) {
+ return nil, nil
+}
+
+func (p *oauth2AuthProvider) GetData() ([]byte, error) {
+ if p.source == nil {
+ // anonymous access
+ return nil, nil
+ }
+ token, err := p.source.Token()
+ if err != nil {
+ return nil, err
+ }
+ return []byte(token.AccessToken), nil
+}
+
+func (p *oauth2AuthProvider) Close() error {
+ return nil
+}
+
+func (p *oauth2AuthProvider) getRefresher(t oauth2.AuthorizationGrantType) (oauth2.AuthorizationGrantRefresher, error) {
+ switch t {
+ case oauth2.GrantTypeClientCredentials:
+ return oauth2.NewDefaultClientCredentialsGrantRefresher(p.clock)
+ case oauth2.GrantTypeDeviceCode:
+ return oauth2.NewDefaultDeviceAuthorizationGrantRefresher(p.clock)
+ default:
+ return nil, store.ErrUnsupportedAuthData
+ }
+}
+
+type transport struct {
+ source cache.CachingTokenSource
+ wrapped *xoauth2.Transport
+}
+
+func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
+ if len(req.Header.Get("Authorization")) != 0 {
+ return t.wrapped.Base.RoundTrip(req)
+ }
+
+ res, err := t.wrapped.RoundTrip(req)
+ if err != nil {
+ return nil, err
+ }
+
+ if res.StatusCode == 401 {
+ err := t.source.InvalidateToken()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return res, nil
+}
+
+func (t *transport) WrappedRoundTripper() http.RoundTripper { return t.wrapped.Base }
+
+func (p *oauth2AuthProvider) RoundTrip(req *http.Request) (*http.Response, error) {
+ return p.tokenTransport.RoundTrip(req)
+}
+
+func (p *oauth2AuthProvider) Transport() http.RoundTripper {
+ return &transport{
+ source: p.source,
+ wrapped: &xoauth2.Transport{
+ Source: p.source,
+ Base: p.defaultTransport,
+ },
+ }
+}
+
+func (p *oauth2AuthProvider) WithTransport(tripper http.RoundTripper) error {
+ p.defaultTransport = tripper
+ p.tokenTransport = &transport{
+ source: p.source,
+ wrapped: &xoauth2.Transport{
+ Source: p.source,
+ Base: p.defaultTransport,
+ },
+ }
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/auth/provider.go b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/provider.go
new file mode 100644
index 00000000..031ea8d6
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/provider.go
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+ "crypto/tls"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+// Provider is an interface of authentication providers.
+type Provider interface {
+ // Init the authentication provider.
+ Init() error
+
+ // Name func returns the identifier for this authentication method.
+ Name() string
+
+ // GetTLSCertificate returns a client certificate chain, or nil if the data are not available
+ GetTLSCertificate() (*tls.Certificate, error)
+
+ // GetData returns the authentication data identifying this client that will be sent to the broker.
+ GetData() ([]byte, error)
+
+ io.Closer
+
+ HTTPAuthProvider
+}
+
+type HTTPAuthProvider interface {
+ RoundTrip(req *http.Request) (*http.Response, error)
+ Transport() http.RoundTripper
+ WithTransport(tripper http.RoundTripper) error
+}
+
+type HTTPTransport struct {
+ T http.RoundTripper
+}
+
+// NewProvider get/create an authentication data provider which provides the data
+// that this client will be sent to the broker.
+// Some authentication method need to auth between each client channel. So it need
+// the broker, who it will talk to.
+func NewProvider(name string, params string) (Provider, error) {
+ m, err := parseParams(params)
+ if err != nil {
+ return nil, err
+ }
+
+ switch name {
+ case "":
+ return NewAuthDisabled(), nil
+
+ case "tls", "org.apache.pulsar.client.impl.auth.AuthenticationTls":
+ return NewAuthenticationTLSWithParams(m), nil
+
+ case "token", "org.apache.pulsar.client.impl.auth.AuthenticationToken":
+ return NewAuthenticationTokenWithParams(m)
+
+ case "athenz", "org.apache.pulsar.client.impl.auth.AuthenticationAthenz":
+ return NewAuthenticationAthenzWithParams(m)
+
+ case "oauth2", "org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2":
+ return NewAuthenticationOAuth2WithParams(m)
+
+ case "basic", "org.apache.pulsar.client.impl.auth.AuthenticationBasic":
+ return NewAuthenticationBasicWithParams(m)
+
+ default:
+ return nil, fmt.Errorf("invalid auth provider '%s'", name)
+ }
+}
+
+func parseParams(params string) (map[string]string, error) {
+ var mapString map[string]string
+ if err := json.Unmarshal([]byte(params), &mapString); err != nil {
+ return nil, err
+ }
+
+ return mapString, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/auth/tls.go b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/tls.go
new file mode 100644
index 00000000..4b5b9cd9
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/tls.go
@@ -0,0 +1,101 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+ "crypto/tls"
+ "net/http"
+)
+
+type tlsAuthProvider struct {
+ certificatePath string
+ privateKeyPath string
+ tlsCertSupplier func() (*tls.Certificate, error)
+ T http.RoundTripper
+}
+
+// NewAuthenticationTLSWithParams initialize the authentication provider with map param.
+func NewAuthenticationTLSWithParams(params map[string]string) Provider {
+ return NewAuthenticationTLS(
+ params["tlsCertFile"],
+ params["tlsKeyFile"],
+ )
+}
+
+// NewAuthenticationTLS initialize the authentication provider
+func NewAuthenticationTLS(certificatePath string, privateKeyPath string) Provider {
+ return &tlsAuthProvider{
+ certificatePath: certificatePath,
+ privateKeyPath: privateKeyPath,
+ }
+}
+
+func NewAuthenticationFromTLSCertSupplier(tlsCertSupplier func() (*tls.Certificate, error)) Provider {
+ return &tlsAuthProvider{
+ tlsCertSupplier: tlsCertSupplier,
+ }
+}
+
+func (p *tlsAuthProvider) Init() error {
+ // Try to read certificates immediately to provide better error at startup
+ _, err := p.GetTLSCertificate()
+ return err
+}
+
+func (p *tlsAuthProvider) Name() string {
+ return "tls"
+}
+
+func (p *tlsAuthProvider) GetTLSCertificate() (*tls.Certificate, error) {
+ if p.tlsCertSupplier != nil {
+ return p.tlsCertSupplier()
+ }
+ cert, err := tls.LoadX509KeyPair(p.certificatePath, p.privateKeyPath)
+ return &cert, err
+}
+
+func (p *tlsAuthProvider) GetData() ([]byte, error) {
+ return nil, nil
+}
+
+func (tlsAuthProvider) Close() error {
+ return nil
+}
+
+func (p *tlsAuthProvider) RoundTrip(req *http.Request) (*http.Response, error) {
+ return p.T.RoundTrip(req)
+}
+
+func (p *tlsAuthProvider) Transport() http.RoundTripper {
+ return p.T
+}
+
+func (p *tlsAuthProvider) WithTransport(tripper http.RoundTripper) error {
+ p.T = tripper
+ return p.configTLS()
+}
+
+func (p *tlsAuthProvider) configTLS() error {
+ cert, err := p.GetTLSCertificate()
+ if err != nil {
+ return err
+ }
+ transport := p.T.(*http.Transport)
+ transport.TLSClientConfig.Certificates = []tls.Certificate{*cert}
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/auth/token.go b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/token.go
new file mode 100644
index 00000000..898b6537
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/auth/token.go
@@ -0,0 +1,125 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+ "crypto/tls"
+ "fmt"
+ "net/http"
+ "os"
+ "strings"
+
+ "github.com/pkg/errors"
+)
+
+type tokenAuthProvider struct {
+ tokenSupplier func() (string, error)
+ T http.RoundTripper
+}
+
+// NewAuthenticationTokenWithParams return a interface of Provider with string map.
+func NewAuthenticationTokenWithParams(params map[string]string) (Provider, error) {
+ if params["token"] != "" {
+ return NewAuthenticationToken(params["token"]), nil
+ } else if params["file"] != "" {
+ return NewAuthenticationTokenFromFile(params["file"]), nil
+ } else {
+ return nil, errors.New("missing configuration for token auth")
+ }
+}
+
+// NewAuthenticationToken returns a token auth provider that will use the specified token to
+// talk with Pulsar brokers
+func NewAuthenticationToken(token string) Provider {
+ return &tokenAuthProvider{
+ tokenSupplier: func() (string, error) {
+ if token == "" {
+ return "", errors.New("empty token credentials")
+ }
+ return token, nil
+ },
+ }
+}
+
+// NewAuthenticationTokenFromSupplier returns a token auth provider that get
+// the token data from a user supplied function. The function is invoked each
+// time the client library needs to use a token in talking with Pulsar brokers
+func NewAuthenticationTokenFromSupplier(tokenSupplier func() (string, error)) Provider {
+ return &tokenAuthProvider{
+ tokenSupplier: tokenSupplier,
+ }
+}
+
+// NewAuthenticationTokenFromFile return a interface of a Provider with a string token file path.
+func NewAuthenticationTokenFromFile(tokenFilePath string) Provider {
+ return &tokenAuthProvider{
+ tokenSupplier: func() (string, error) {
+ data, err := os.ReadFile(tokenFilePath)
+ if err != nil {
+ return "", err
+ }
+
+ token := strings.Trim(string(data), " \n")
+ if token == "" {
+ return "", errors.New("empty token credentials")
+ }
+ return token, nil
+ },
+ }
+}
+
+func (p *tokenAuthProvider) Init() error {
+ // Try to read certificates immediately to provide better error at startup
+ _, err := p.GetData()
+ return err
+}
+
+func (p *tokenAuthProvider) Name() string {
+ return "token"
+}
+
+func (p *tokenAuthProvider) GetTLSCertificate() (*tls.Certificate, error) {
+ return nil, nil
+}
+
+func (p *tokenAuthProvider) GetData() ([]byte, error) {
+ t, err := p.tokenSupplier()
+ if err != nil {
+ return nil, err
+ }
+ return []byte(t), nil
+}
+
+func (p *tokenAuthProvider) Close() error {
+ return nil
+}
+
+func (p *tokenAuthProvider) RoundTrip(req *http.Request) (*http.Response, error) {
+ token, _ := p.tokenSupplier()
+ req.Header.Add("Authorization", strings.TrimSpace(fmt.Sprintf("Bearer %s", token)))
+ return p.T.RoundTrip(req)
+}
+
+func (p *tokenAuthProvider) Transport() http.RoundTripper {
+ return p.T
+}
+
+func (p *tokenAuthProvider) WithTransport(tripper http.RoundTripper) error {
+ p.T = tripper
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/batcher_builder.go b/vendor/github.com/apache/pulsar-client-go/pulsar/batcher_builder.go
new file mode 100644
index 00000000..05e059b0
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/batcher_builder.go
@@ -0,0 +1,42 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+)
+
+type BatcherBuilderType int
+
+const (
+ DefaultBatchBuilder BatcherBuilderType = iota
+ KeyBasedBatchBuilder
+)
+
+func GetBatcherBuilderProvider(typ BatcherBuilderType) (
+ internal.BatcherBuilderProvider, error,
+) {
+ switch typ {
+ case DefaultBatchBuilder:
+ return internal.NewBatchBuilder, nil
+ case KeyBasedBatchBuilder:
+ return internal.NewKeyBasedBatchBuilder, nil
+ default:
+ return nil, newError(InvalidBatchBuilderType, "unsupported batcher builder provider type")
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/client.go b/vendor/github.com/apache/pulsar-client-go/pulsar/client.go
new file mode 100644
index 00000000..bc3f4f58
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/client.go
@@ -0,0 +1,200 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "crypto/tls"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/auth"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// NewClient Creates a pulsar client instance
+func NewClient(options ClientOptions) (Client, error) {
+ return newClient(options)
+}
+
+// Authentication Opaque interface that represents the authentication credentials
+type Authentication interface{}
+
+// NewAuthentication Creates an authentication by name and params
+func NewAuthentication(name string, params string) (Authentication, error) {
+ return auth.NewProvider(name, params)
+}
+
+// NewAuthenticationToken Creates new Authentication provider with specified auth token
+func NewAuthenticationToken(token string) Authentication {
+ return auth.NewAuthenticationToken(token)
+}
+
+// NewAuthenticationTokenFromSupplier returns a token auth provider that
+// gets the token data from a user supplied function. The function is
+// invoked each time the client library needs to use a token in talking
+// with Pulsar brokers
+func NewAuthenticationTokenFromSupplier(tokenSupplier func() (string, error)) Authentication {
+ return auth.NewAuthenticationTokenFromSupplier(tokenSupplier)
+}
+
+// NewAuthenticationTokenFromFile Creates new Authentication provider with specified auth token from a file
+func NewAuthenticationTokenFromFile(tokenFilePath string) Authentication {
+ return auth.NewAuthenticationTokenFromFile(tokenFilePath)
+}
+
+// NewAuthenticationTLS Creates new Authentication provider with specified TLS certificate and private key
+func NewAuthenticationTLS(certificatePath string, privateKeyPath string) Authentication {
+ return auth.NewAuthenticationTLS(certificatePath, privateKeyPath)
+}
+
+// NewAuthenticationFromTLSCertSupplier Create new Authentication provider with specified TLS certificate supplier
+func NewAuthenticationFromTLSCertSupplier(tlsCertSupplier func() (*tls.Certificate, error)) Authentication {
+ return auth.NewAuthenticationFromTLSCertSupplier(tlsCertSupplier)
+}
+
+// NewAuthenticationAthenz Creates Athenz Authentication provider
+func NewAuthenticationAthenz(authParams map[string]string) Authentication {
+ athenz, _ := auth.NewAuthenticationAthenzWithParams(authParams)
+ return athenz
+}
+
+// NewAuthenticationOAuth2 Creates OAuth2 Authentication provider
+func NewAuthenticationOAuth2(authParams map[string]string) Authentication {
+ oauth, _ := auth.NewAuthenticationOAuth2WithParams(authParams)
+ return oauth
+}
+
+// NewAuthenticationBasic Creates Basic Authentication provider
+func NewAuthenticationBasic(username, password string) (Authentication, error) {
+ return auth.NewAuthenticationBasic(username, password)
+}
+
+// ClientOptions is used to construct a Pulsar Client instance.
+type ClientOptions struct {
+ // Configure the service URL for the Pulsar service.
+ // This parameter is required
+ URL string
+
+ // Timeout for the establishment of a TCP connection (default: 5 seconds)
+ ConnectionTimeout time.Duration
+
+ // Set the operation timeout (default: 30 seconds)
+ // Producer-create, subscribe and unsubscribe operations will be retried until this interval, after which the
+ // operation will be marked as failed
+ OperationTimeout time.Duration
+
+ // Configure the ping send and check interval, default to 30 seconds.
+ KeepAliveInterval time.Duration
+
+ // Configure the authentication provider. (default: no authentication)
+ // Example: `Authentication: NewAuthenticationTLS("my-cert.pem", "my-key.pem")`
+ Authentication
+
+ // Set the path to the TLS key file
+ TLSKeyFilePath string
+
+ // Set the path to the TLS certificate file
+ TLSCertificateFile string
+
+ // Set the path to the trusted TLS certificate file
+ TLSTrustCertsFilePath string
+
+ // Configure whether the Pulsar client accept untrusted TLS certificate from broker (default: false)
+ TLSAllowInsecureConnection bool
+
+ // Configure whether the Pulsar client verify the validity of the host name from broker (default: false)
+ TLSValidateHostname bool
+
+ // Configure the net model for vpc user to connect the pulsar broker
+ ListenerName string
+
+ // Max number of connections to a single broker that will kept in the pool. (Default: 1 connection)
+ MaxConnectionsPerBroker int
+
+ // Configure the logger used by the client.
+ // By default, a wrapped logrus.StandardLogger will be used, namely,
+ // log.NewLoggerWithLogrus(logrus.StandardLogger())
+ // FIXME: use `logger` as internal field name instead of `log` as it's more idiomatic
+ Logger log.Logger
+
+ // Specify metric cardinality to the tenant, namespace or topic levels, or remove it completely.
+ // Default: MetricsCardinalityNamespace
+ MetricsCardinality MetricsCardinality
+
+ // Add custom labels to all the metrics reported by this client instance
+ CustomMetricsLabels map[string]string
+
+ // Specify metric registerer used to register metrics.
+ // Default prometheus.DefaultRegisterer
+ MetricsRegisterer prometheus.Registerer
+
+ // Release the connection if it is not used for more than ConnectionMaxIdleTime.
+ // Default is 60 seconds, negative such as -1 to disable.
+ ConnectionMaxIdleTime time.Duration
+
+ EnableTransaction bool
+
+ // Limit of client memory usage (in byte). The 64M default can guarantee a high producer throughput.
+ // Config less than 0 indicates off memory limit.
+ MemoryLimitBytes int64
+}
+
+// Client represents a pulsar client
+type Client interface {
+ // CreateProducer Creates the producer instance
+ // This method will block until the producer is created successfully
+ CreateProducer(ProducerOptions) (Producer, error)
+
+ // Subscribe Creates a `Consumer` by subscribing to a topic.
+ //
+ // If the subscription does not exist, a new subscription will be created and all messages published after the
+ // creation will be retained until acknowledged, even if the consumer is not connected
+ Subscribe(ConsumerOptions) (Consumer, error)
+
+ // CreateReader Creates a Reader instance.
+ // This method will block until the reader is created successfully.
+ CreateReader(ReaderOptions) (Reader, error)
+
+ // CreateTableView creates a table view instance.
+ // This method will block until the table view is created successfully.
+ CreateTableView(TableViewOptions) (TableView, error)
+
+ // TopicPartitions Fetches the list of partitions for a given topic
+ //
+ // If the topic is partitioned, this will return a list of partition names.
+ // If the topic is not partitioned, the returned list will contain the topic
+ // name itself.
+ //
+ // This can be used to discover the partitions and create {@link Reader},
+ // {@link Consumer} or {@link Producer} instances directly on a particular partition.
+ TopicPartitions(topic string) ([]string, error)
+
+ // Close Closes the Client and free associated resources
+ Close()
+}
+
+// MetricsCardinality represents the specificty of labels on a per-metric basis
+type MetricsCardinality int
+
+const (
+ _ MetricsCardinality = iota
+ MetricsCardinalityNone // Do not add additional labels to metrics
+ MetricsCardinalityTenant // Label metrics by tenant
+ MetricsCardinalityNamespace // Label metrics by tenant and namespace
+ MetricsCardinalityTopic // Label metrics by topic
+)
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/client_impl.go b/vendor/github.com/apache/pulsar-client-go/pulsar/client_impl.go
new file mode 100644
index 00000000..53225975
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/client_impl.go
@@ -0,0 +1,261 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "fmt"
+ "net/url"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/auth"
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ defaultConnectionTimeout = 10 * time.Second
+ defaultOperationTimeout = 30 * time.Second
+ defaultKeepAliveInterval = 30 * time.Second
+ defaultMemoryLimitBytes = 64 * 1024 * 1024
+ defaultMemoryLimitTriggerThreshold = 0.95
+ defaultConnMaxIdleTime = 180 * time.Second
+ minConnMaxIdleTime = 60 * time.Second
+)
+
+type client struct {
+ cnxPool internal.ConnectionPool
+ rpcClient internal.RPCClient
+ handlers internal.ClientHandlers
+ lookupService internal.LookupService
+ metrics *internal.Metrics
+ tcClient *transactionCoordinatorClient
+ memLimit internal.MemoryLimitController
+
+ log log.Logger
+}
+
+func newClient(options ClientOptions) (Client, error) {
+ var logger log.Logger
+ if options.Logger != nil {
+ logger = options.Logger
+ } else {
+ logger = log.NewLoggerWithLogrus(logrus.StandardLogger())
+ }
+
+ connectionMaxIdleTime := options.ConnectionMaxIdleTime
+ if connectionMaxIdleTime == 0 {
+ connectionMaxIdleTime = defaultConnMaxIdleTime
+ } else if connectionMaxIdleTime > 0 && connectionMaxIdleTime < minConnMaxIdleTime {
+ return nil, newError(InvalidConfiguration, fmt.Sprintf("Connection max idle time should be at least %f "+
+ "seconds", minConnMaxIdleTime.Seconds()))
+ } else {
+ logger.Debugf("Disable auto release idle connections")
+ }
+
+ if options.URL == "" {
+ return nil, newError(InvalidConfiguration, "URL is required for client")
+ }
+
+ url, err := url.Parse(options.URL)
+ if err != nil {
+ logger.WithError(err).Error("Failed to parse service URL")
+ return nil, newError(InvalidConfiguration, "Invalid service URL")
+ }
+
+ var tlsConfig *internal.TLSOptions
+ switch url.Scheme {
+ case "pulsar", "http":
+ tlsConfig = nil
+ case "pulsar+ssl", "https":
+ tlsConfig = &internal.TLSOptions{
+ AllowInsecureConnection: options.TLSAllowInsecureConnection,
+ KeyFile: options.TLSKeyFilePath,
+ CertFile: options.TLSCertificateFile,
+ TrustCertsFilePath: options.TLSTrustCertsFilePath,
+ ValidateHostname: options.TLSValidateHostname,
+ ServerName: url.Hostname(),
+ }
+ default:
+ return nil, newError(InvalidConfiguration, fmt.Sprintf("Invalid URL scheme '%s'", url.Scheme))
+ }
+
+ var authProvider auth.Provider
+ var ok bool
+
+ if options.Authentication == nil {
+ authProvider = auth.NewAuthDisabled()
+ } else {
+ authProvider, ok = options.Authentication.(auth.Provider)
+ if !ok {
+ return nil, newError(AuthenticationError, "invalid auth provider interface")
+ }
+ }
+ err = authProvider.Init()
+ if err != nil {
+ return nil, err
+ }
+
+ connectionTimeout := options.ConnectionTimeout
+ if connectionTimeout.Nanoseconds() == 0 {
+ connectionTimeout = defaultConnectionTimeout
+ }
+
+ operationTimeout := options.OperationTimeout
+ if operationTimeout.Nanoseconds() == 0 {
+ operationTimeout = defaultOperationTimeout
+ }
+
+ maxConnectionsPerHost := options.MaxConnectionsPerBroker
+ if maxConnectionsPerHost <= 0 {
+ maxConnectionsPerHost = 1
+ }
+
+ if options.MetricsCardinality == 0 {
+ options.MetricsCardinality = MetricsCardinalityNamespace
+ }
+
+ if options.MetricsRegisterer == nil {
+ options.MetricsRegisterer = prometheus.DefaultRegisterer
+ }
+
+ var metrics *internal.Metrics
+ if options.CustomMetricsLabels != nil {
+ metrics = internal.NewMetricsProvider(
+ int(options.MetricsCardinality), options.CustomMetricsLabels, options.MetricsRegisterer)
+ } else {
+ metrics = internal.NewMetricsProvider(
+ int(options.MetricsCardinality), map[string]string{}, options.MetricsRegisterer)
+ }
+
+ keepAliveInterval := options.KeepAliveInterval
+ if keepAliveInterval.Nanoseconds() == 0 {
+ keepAliveInterval = defaultKeepAliveInterval
+ }
+
+ memLimitBytes := options.MemoryLimitBytes
+ if memLimitBytes == 0 {
+ memLimitBytes = defaultMemoryLimitBytes
+ }
+
+ c := &client{
+ cnxPool: internal.NewConnectionPool(tlsConfig, authProvider, connectionTimeout, keepAliveInterval,
+ maxConnectionsPerHost, logger, metrics, connectionMaxIdleTime),
+ log: logger,
+ metrics: metrics,
+ memLimit: internal.NewMemoryLimitController(memLimitBytes, defaultMemoryLimitTriggerThreshold),
+ }
+ serviceNameResolver := internal.NewPulsarServiceNameResolver(url)
+
+ c.rpcClient = internal.NewRPCClient(url, serviceNameResolver, c.cnxPool, operationTimeout, logger, metrics)
+
+ switch url.Scheme {
+ case "pulsar", "pulsar+ssl":
+ c.lookupService = internal.NewLookupService(c.rpcClient, url, serviceNameResolver,
+ tlsConfig != nil, options.ListenerName, logger, metrics)
+ case "http", "https":
+ httpClient, err := internal.NewHTTPClient(url, serviceNameResolver, tlsConfig,
+ operationTimeout, logger, metrics, authProvider)
+ if err != nil {
+ return nil, newError(InvalidConfiguration, fmt.Sprintf("Failed to init http client with err: '%s'",
+ err.Error()))
+ }
+ c.lookupService = internal.NewHTTPLookupService(httpClient, url, serviceNameResolver,
+ tlsConfig != nil, logger, metrics)
+ default:
+ return nil, newError(InvalidConfiguration, fmt.Sprintf("Invalid URL scheme '%s'", url.Scheme))
+ }
+
+ c.handlers = internal.NewClientHandlers()
+
+ if options.EnableTransaction {
+ c.tcClient = newTransactionCoordinatorClientImpl(c)
+ err = c.tcClient.start()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return c, nil
+}
+
+func (c *client) CreateProducer(options ProducerOptions) (Producer, error) {
+ producer, err := newProducer(c, &options)
+ if err == nil {
+ c.handlers.Add(producer)
+ }
+ return producer, err
+}
+
+func (c *client) Subscribe(options ConsumerOptions) (Consumer, error) {
+ consumer, err := newConsumer(c, options)
+ if err != nil {
+ return nil, err
+ }
+ c.handlers.Add(consumer)
+ return consumer, nil
+}
+
+func (c *client) CreateReader(options ReaderOptions) (Reader, error) {
+ reader, err := newReader(c, options)
+ if err != nil {
+ return nil, err
+ }
+ c.handlers.Add(reader)
+ return reader, nil
+}
+
+func (c *client) CreateTableView(options TableViewOptions) (TableView, error) {
+ tableView, err := newTableView(c, options)
+ if err != nil {
+ return nil, err
+ }
+ c.handlers.Add(tableView)
+ return tableView, nil
+}
+
+func (c *client) TopicPartitions(topic string) ([]string, error) {
+ topicName, err := internal.ParseTopicName(topic)
+ if err != nil {
+ return nil, err
+ }
+
+ r, err := c.lookupService.GetPartitionedTopicMetadata(topic)
+ if err != nil {
+ return nil, err
+ }
+ if r != nil {
+ if r.Partitions > 0 {
+ partitions := make([]string, r.Partitions)
+ for i := 0; i < r.Partitions; i++ {
+ partitions[i] = fmt.Sprintf("%s-partition-%d", topic, i)
+ }
+ return partitions, nil
+ }
+ }
+
+ // Non-partitioned topic
+ return []string{topicName.Name}, nil
+}
+
+func (c *client) Close() {
+ c.handlers.Close()
+ c.cnxPool.Close()
+ c.lookupService.Close()
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/consumer.go b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer.go
new file mode 100644
index 00000000..64a096d5
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer.go
@@ -0,0 +1,319 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+)
+
+// ConsumerMessage represents a pair of a Consumer and Message.
+type ConsumerMessage struct {
+ Consumer
+ Message
+}
+
+// SubscriptionType of subscription supported by Pulsar
+type SubscriptionType int
+
+const (
+ // Exclusive there can be only 1 consumer on the same topic with the same subscription name
+ Exclusive SubscriptionType = iota
+
+ // Shared subscription mode, multiple consumer will be able to use the same subscription name
+ // and the messages will be dispatched according to
+ // a round-robin rotation between the connected consumers
+ Shared
+
+ // Failover subscription mode, multiple consumer will be able to use the same subscription name
+ // but only 1 consumer will receive the messages.
+ // If that consumer disconnects, one of the other connected consumers will start receiving messages.
+ Failover
+
+ // KeyShared subscription mode, multiple consumer will be able to use the same
+ // subscription and all messages with the same key will be dispatched to only one consumer
+ KeyShared
+)
+
+type SubscriptionInitialPosition int
+
+const (
+ // SubscriptionPositionLatest is the latest position which means the start consuming position
+ // will be the last message
+ SubscriptionPositionLatest SubscriptionInitialPosition = iota
+
+ // SubscriptionPositionEarliest is the earliest position which means the start consuming position
+ // will be the first message
+ SubscriptionPositionEarliest
+)
+
+// DLQPolicy represents the configuration for the Dead Letter Queue consumer policy.
+type DLQPolicy struct {
+ // MaxDeliveries specifies the maximum number of times that a message will be delivered before being
+ // sent to the dead letter queue.
+ MaxDeliveries uint32
+
+ // DeadLetterTopic specifies the name of the topic where the failing messages will be sent.
+ DeadLetterTopic string
+
+ // ProducerOptions is the producer options to produce messages to the DLQ and RLQ topic
+ ProducerOptions ProducerOptions
+
+ // RetryLetterTopic specifies the name of the topic where the retry messages will be sent.
+ RetryLetterTopic string
+}
+
+// AckGroupingOptions controls how to group ACK requests
+// If maxSize is 0 or 1, any ACK request will be sent immediately.
+// Otherwise, the ACK requests will be cached until one of the following conditions meets:
+// 1. There are `MaxSize` pending ACK requests.
+// 2. `MaxTime` is greater than 1 microsecond and ACK requests have been cached for `maxTime`.
+// Specially, for cumulative acknowledgment, only the latest ACK is cached and it will only be sent after `MaxTime`.
+type AckGroupingOptions struct {
+ // The maximum number of ACK requests to cache
+ MaxSize uint32
+
+ // The maximum time to cache ACK requests
+ MaxTime time.Duration
+}
+
+// ConsumerOptions is used to configure and create instances of Consumer.
+type ConsumerOptions struct {
+ // Topic specifies the topic this consumer will subscribe on.
+ // Either a topic, a list of topics or a topics pattern are required when subscribing
+ Topic string
+
+ // Topics specifies a list of topics this consumer will subscribe on.
+ // Either a topic, a list of topics or a topics pattern are required when subscribing
+ Topics []string
+
+ // TopicsPattern specifies a regular expression to subscribe to multiple topics under the same namespace.
+ // Either a topic, a list of topics or a topics pattern are required when subscribing
+ TopicsPattern string
+
+ // AutoDiscoveryPeriod specifies the interval in which to poll for new partitions or new topics
+ // if using a TopicsPattern.
+ AutoDiscoveryPeriod time.Duration
+
+ // SubscriptionName specifies the subscription name for this consumer
+ // This argument is required when subscribing
+ SubscriptionName string
+
+ // Properties represents a set of application defined properties for the consumer.
+ // Those properties will be visible in the topic stats
+ Properties map[string]string
+
+ // SubscriptionProperties specify the subscription properties for this subscription.
+ //
+ // > Notice: SubscriptionProperties are immutable, and consumers under the same subscription will fail to create a
+ // > subscription if they use different properties.
+ SubscriptionProperties map[string]string
+
+ // Type specifies the subscription type to be used when subscribing to a topic.
+ // Default is `Exclusive`
+ Type SubscriptionType
+
+ // SubscriptionInitialPosition is the initial position at which the cursor will be set when subscribe
+ // Default is `Latest`
+ SubscriptionInitialPosition
+
+ // EventListener will be called when active consumer changed (in failover subscription type)
+ EventListener ConsumerEventListener
+
+ // DLQ represents the configuration for Dead Letter Queue consumer policy.
+ // eg. route the message to topic X after N failed attempts at processing it
+ // By default is nil and there's no DLQ
+ DLQ *DLQPolicy
+
+ // KeySharedPolicy represents the configuration for Key Shared consumer policy.
+ KeySharedPolicy *KeySharedPolicy
+
+ // RetryEnable determines whether to automatically retry sending messages to default filled DLQPolicy topics.
+ // Default is false
+ RetryEnable bool
+
+ // MessageChannel sets a `MessageChannel` for the consumer
+ // When a message is received, it will be pushed to the channel for consumption
+ MessageChannel chan ConsumerMessage
+
+ // ReceiverQueueSize sets the size of the consumer receive queue.
+ // The consumer receive queue controls how many messages can be accumulated by the `Consumer` before the
+ // application calls `Consumer.receive()`. Using a higher value could potentially increase the consumer
+ // throughput at the expense of bigger memory utilization.
+ // Default value is `1000` messages and should be good for most use cases.
+ ReceiverQueueSize int
+
+ // EnableAutoScaledReceiverQueueSize, if enabled, the consumer receive queue will be auto-scaled
+ // by the consumer actual throughput. The ReceiverQueueSize will be the maximum size which consumer
+ // receive queue can be scaled.
+ // Default is false.
+ EnableAutoScaledReceiverQueueSize bool
+
+ // NackRedeliveryDelay specifies the delay after which to redeliver the messages that failed to be
+ // processed. Default is 1 min. (See `Consumer.Nack()`)
+ NackRedeliveryDelay time.Duration
+
+ // Name specifies the consumer name.
+ Name string
+
+ // ReadCompacted, if enabled, the consumer will read messages from the compacted topic rather than reading the
+ // full message backlog of the topic. This means that, if the topic has been compacted, the consumer will only
+ // see the latest value for each key in the topic, up until the point in the topic message backlog that has been
+ // compacted. Beyond that point, the messages will be sent as normal.
+ //
+ // ReadCompacted can only be enabled subscriptions to persistent topics, which have a single active consumer (i.e.
+ // failure or exclusive subscriptions). Attempting to enable it on subscriptions to a non-persistent topics or on a
+ // shared subscription, will lead to the subscription call throwing a PulsarClientException.
+ ReadCompacted bool
+
+ // ReplicateSubscriptionState marks the subscription as replicated to keep it in sync across clusters
+ ReplicateSubscriptionState bool
+
+ // Interceptors is a chain of interceptors. These interceptors will be called at some points defined in
+ // ConsumerInterceptor interface.
+ Interceptors ConsumerInterceptors
+
+ // Schema represents the schema implementation.
+ Schema Schema
+
+ // MaxReconnectToBroker sets the maximum retry number of reconnectToBroker. (default: ultimate)
+ MaxReconnectToBroker *uint
+
+ // BackoffPolicy parameterize the following options in the reconnection logic to
+ // allow users to customize the reconnection logic (minBackoff, maxBackoff and jitterPercentage)
+ BackoffPolicy internal.BackoffPolicy
+
+ // Decryption represents the encryption related fields required by the consumer to decrypt a message.
+ Decryption *MessageDecryptionInfo
+
+ // EnableDefaultNackBackoffPolicy, if enabled, the default implementation of NackBackoffPolicy will be used
+ // to calculate the delay time of
+ // nack backoff, Default: false.
+ EnableDefaultNackBackoffPolicy bool
+
+ // NackBackoffPolicy is a redelivery backoff mechanism which we can achieve redelivery with different
+ // delays according to the number of times the message is retried.
+ //
+ // > Notice: the NackBackoffPolicy will not work with `consumer.NackID(MessageID)`
+ // > because we are not able to get the redeliveryCount from the message ID.
+ NackBackoffPolicy NackBackoffPolicy
+
+ // AckWithResponse is a return value added to Ack Command, and its purpose is to confirm whether Ack Command
+ // is executed correctly on the Broker side. When set to true, the error information returned by the Ack
+ // method contains the return value of the Ack Command processed by the Broker side; when set to false, the
+ // error information of the Ack method only contains errors that may occur in the Go SDK's own processing.
+ // Default: false
+ AckWithResponse bool
+
+ // MaxPendingChunkedMessage sets the maximum pending chunked messages. (default: 100)
+ MaxPendingChunkedMessage int
+
+ // ExpireTimeOfIncompleteChunk sets the expiry time of discarding incomplete chunked message. (default: 60 seconds)
+ ExpireTimeOfIncompleteChunk time.Duration
+
+ // AutoAckIncompleteChunk sets whether consumer auto acknowledges incomplete chunked message when it should
+ // be removed (e.g.the chunked message pending queue is full). (default: false)
+ AutoAckIncompleteChunk bool
+
+ // Enable or disable batch index acknowledgment. To enable this feature, ensure batch index acknowledgment
+ // is enabled on the broker side. (default: false)
+ EnableBatchIndexAcknowledgment bool
+
+ // Controls how to group ACK requests, the default value is nil, which means:
+ // MaxSize: 1000
+ // MaxTime: 100*time.Millisecond
+ // NOTE: This option does not work if AckWithResponse is true
+ // because there are only synchronous APIs for acknowledgment
+ AckGroupingOptions *AckGroupingOptions
+}
+
+// Consumer is an interface that abstracts behavior of Pulsar's consumer
+type Consumer interface {
+ // Subscription get a subscription for the consumer
+ Subscription() string
+
+ // Unsubscribe the consumer
+ Unsubscribe() error
+
+ // Receive a single message.
+ // This calls blocks until a message is available.
+ Receive(context.Context) (Message, error)
+
+ // Chan returns a channel to consume messages from
+ Chan() <-chan ConsumerMessage
+
+ // Ack the consumption of a single message
+ Ack(Message) error
+
+ // AckID the consumption of a single message, identified by its MessageID
+ AckID(MessageID) error
+
+ // AckCumulative the reception of all the messages in the stream up to (and including)
+ // the provided message.
+ AckCumulative(msg Message) error
+
+ // AckIDCumulative the reception of all the messages in the stream up to (and including)
+ // the provided message, identified by its MessageID
+ AckIDCumulative(msgID MessageID) error
+
+ // ReconsumeLater mark a message for redelivery after custom delay
+ ReconsumeLater(msg Message, delay time.Duration)
+
+ // ReconsumeLaterWithCustomProperties mark a message for redelivery after custom delay with custom properties
+ ReconsumeLaterWithCustomProperties(msg Message, customProperties map[string]string, delay time.Duration)
+
+ // Nack acknowledges the failure to process a single message.
+ //
+ // When a message is "negatively acked" it will be marked for redelivery after
+ // some fixed delay. The delay is configurable when constructing the consumer
+ // with ConsumerOptions.NackRedeliveryDelay .
+ //
+ // This call is not blocking.
+ Nack(Message)
+
+ // NackID acknowledges the failure to process a single message.
+ //
+ // When a message is "negatively acked" it will be marked for redelivery after
+ // some fixed delay. The delay is configurable when constructing the consumer
+ // with ConsumerOptions.NackRedeliveryDelay .
+ //
+ // This call is not blocking.
+ NackID(MessageID)
+
+ // Close the consumer and stop the broker to push more messages
+ Close()
+
+ // Seek resets the subscription associated with this consumer to a specific message id.
+ // The message id can either be a specific message or represent the first or last messages in the topic.
+ //
+ // Note: this operation can only be done on non-partitioned topics. For these, one can rather perform the
+ // seek() on the individual partitions.
+ Seek(MessageID) error
+
+ // SeekByTime resets the subscription associated with this consumer to a specific message publish time.
+ //
+ // @param time
+ // the message publish time when to reposition the subscription
+ //
+ SeekByTime(time time.Time) error
+
+ // Name returns the name of consumer.
+ Name() string
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_impl.go b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_impl.go
new file mode 100644
index 00000000..fd7fa578
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_impl.go
@@ -0,0 +1,784 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "fmt"
+ "math/rand"
+ "strconv"
+ "sync"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/crypto"
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+ pkgerrors "github.com/pkg/errors"
+)
+
+const defaultNackRedeliveryDelay = 1 * time.Minute
+
+type acker interface {
+ // AckID does not handle errors returned by the Broker side, so no need to wait for doneCh to finish.
+ AckID(id MessageID) error
+ AckIDWithResponse(id MessageID) error
+ AckIDCumulative(msgID MessageID) error
+ AckIDWithResponseCumulative(msgID MessageID) error
+ NackID(id MessageID)
+ NackMsg(msg Message)
+}
+
+type consumer struct {
+ sync.Mutex
+ topic string
+ client *client
+ options ConsumerOptions
+ consumers []*partitionConsumer
+ consumerName string
+ disableForceTopicCreation bool
+
+ // channel used to deliver message to clients
+ messageCh chan ConsumerMessage
+
+ dlq *dlqRouter
+ rlq *retryRouter
+ closeOnce sync.Once
+ closeCh chan struct{}
+ errorCh chan error
+ stopDiscovery func()
+
+ log log.Logger
+ metrics *internal.LeveledMetrics
+}
+
+func newConsumer(client *client, options ConsumerOptions) (Consumer, error) {
+ if options.Topic == "" && options.Topics == nil && options.TopicsPattern == "" {
+ return nil, newError(TopicNotFound, "topic is required")
+ }
+
+ if options.SubscriptionName == "" {
+ return nil, newError(SubscriptionNotFound, "subscription name is required for consumer")
+ }
+
+ if options.ReceiverQueueSize <= 0 {
+ options.ReceiverQueueSize = defaultReceiverQueueSize
+ }
+
+ if options.Interceptors == nil {
+ options.Interceptors = defaultConsumerInterceptors
+ }
+
+ if options.Name == "" {
+ options.Name = generateRandomName()
+ }
+
+ if options.Schema != nil && options.Schema.GetSchemaInfo() != nil {
+ if options.Schema.GetSchemaInfo().Type == NONE {
+ options.Schema = NewBytesSchema(nil)
+ }
+ }
+
+ if options.MaxPendingChunkedMessage == 0 {
+ options.MaxPendingChunkedMessage = 100
+ }
+
+ if options.ExpireTimeOfIncompleteChunk == 0 {
+ options.ExpireTimeOfIncompleteChunk = time.Minute
+ }
+
+ if options.NackBackoffPolicy == nil && options.EnableDefaultNackBackoffPolicy {
+ options.NackBackoffPolicy = new(defaultNackBackoffPolicy)
+ }
+
+ // did the user pass in a message channel?
+ messageCh := options.MessageChannel
+ if options.MessageChannel == nil {
+ messageCh = make(chan ConsumerMessage, 10)
+ }
+
+ if options.RetryEnable {
+ usingTopic := ""
+ if options.Topic != "" {
+ usingTopic = options.Topic
+ } else if len(options.Topics) > 0 {
+ usingTopic = options.Topics[0]
+ }
+ tn, err := internal.ParseTopicName(usingTopic)
+ if err != nil {
+ return nil, err
+ }
+
+ topicName := internal.TopicNameWithoutPartitionPart(tn)
+
+ retryTopic := topicName + "-" + options.SubscriptionName + RetryTopicSuffix
+ dlqTopic := topicName + "-" + options.SubscriptionName + DlqTopicSuffix
+
+ oldRetryTopic := tn.Domain + "://" + tn.Namespace + "/" + options.SubscriptionName + RetryTopicSuffix
+ oldDlqTopic := tn.Domain + "://" + tn.Namespace + "/" + options.SubscriptionName + DlqTopicSuffix
+
+ if r, err := client.lookupService.GetPartitionedTopicMetadata(oldRetryTopic); err == nil &&
+ r != nil &&
+ r.Partitions > 0 {
+ retryTopic = oldRetryTopic
+ }
+
+ if r, err := client.lookupService.GetPartitionedTopicMetadata(oldDlqTopic); err == nil &&
+ r != nil &&
+ r.Partitions > 0 {
+ dlqTopic = oldDlqTopic
+ }
+
+ if options.DLQ == nil {
+ options.DLQ = &DLQPolicy{
+ MaxDeliveries: MaxReconsumeTimes,
+ DeadLetterTopic: dlqTopic,
+ RetryLetterTopic: retryTopic,
+ }
+ } else {
+ if options.DLQ.DeadLetterTopic == "" {
+ options.DLQ.DeadLetterTopic = dlqTopic
+ }
+ if options.DLQ.RetryLetterTopic == "" {
+ options.DLQ.RetryLetterTopic = retryTopic
+ }
+ }
+ if options.Topic != "" && len(options.Topics) == 0 {
+ options.Topics = []string{options.Topic, options.DLQ.RetryLetterTopic}
+ options.Topic = ""
+ } else if options.Topic == "" && len(options.Topics) > 0 {
+ options.Topics = append(options.Topics, options.DLQ.RetryLetterTopic)
+ }
+ }
+
+ dlq, err := newDlqRouter(client, options.DLQ, client.log)
+ if err != nil {
+ return nil, err
+ }
+ rlq, err := newRetryRouter(client, options.DLQ, options.RetryEnable, client.log)
+ if err != nil {
+ return nil, err
+ }
+
+ // normalize as FQDN topics
+ var tns []*internal.TopicName
+ // single topic consumer
+ if options.Topic != "" || len(options.Topics) == 1 {
+ topic := options.Topic
+ if topic == "" {
+ topic = options.Topics[0]
+ }
+
+ if tns, err = validateTopicNames(topic); err != nil {
+ return nil, err
+ }
+ topic = tns[0].Name
+ err = addMessageCryptoIfMissing(client, &options, topic)
+ if err != nil {
+ return nil, err
+ }
+ return newInternalConsumer(client, options, topic, messageCh, dlq, rlq, false)
+ }
+
+ if len(options.Topics) > 1 {
+ if tns, err = validateTopicNames(options.Topics...); err != nil {
+ return nil, err
+ }
+ for i := range options.Topics {
+ options.Topics[i] = tns[i].Name
+ }
+ options.Topics = distinct(options.Topics)
+
+ err = addMessageCryptoIfMissing(client, &options, options.Topics)
+ if err != nil {
+ return nil, err
+ }
+
+ return newMultiTopicConsumer(client, options, options.Topics, messageCh, dlq, rlq)
+ }
+
+ if options.TopicsPattern != "" {
+ tn, err := internal.ParseTopicName(options.TopicsPattern)
+ if err != nil {
+ return nil, err
+ }
+
+ pattern, err := extractTopicPattern(tn)
+ if err != nil {
+ return nil, err
+ }
+
+ err = addMessageCryptoIfMissing(client, &options, tn.Name)
+ if err != nil {
+ return nil, err
+ }
+
+ return newRegexConsumer(client, options, tn, pattern, messageCh, dlq, rlq)
+ }
+
+ return nil, newError(InvalidTopicName, "topic name is required for consumer")
+}
+
+func newInternalConsumer(client *client, options ConsumerOptions, topic string,
+ messageCh chan ConsumerMessage, dlq *dlqRouter, rlq *retryRouter, disableForceTopicCreation bool) (*consumer, error) {
+
+ consumer := &consumer{
+ topic: topic,
+ client: client,
+ options: options,
+ disableForceTopicCreation: disableForceTopicCreation,
+ messageCh: messageCh,
+ closeCh: make(chan struct{}),
+ errorCh: make(chan error),
+ dlq: dlq,
+ rlq: rlq,
+ log: client.log.SubLogger(log.Fields{"topic": topic}),
+ consumerName: options.Name,
+ metrics: client.metrics.GetLeveledMetrics(topic),
+ }
+
+ err := consumer.internalTopicSubscribeToPartitions()
+ if err != nil {
+ return nil, err
+ }
+
+ // set up timer to monitor for new partitions being added
+ duration := options.AutoDiscoveryPeriod
+ if duration <= 0 {
+ duration = defaultAutoDiscoveryDuration
+ }
+ consumer.stopDiscovery = consumer.runBackgroundPartitionDiscovery(duration)
+
+ consumer.metrics.ConsumersOpened.Inc()
+ return consumer, nil
+}
+
+// Name returns the name of consumer.
+func (c *consumer) Name() string {
+ return c.consumerName
+}
+
+func (c *consumer) runBackgroundPartitionDiscovery(period time.Duration) (cancel func()) {
+ var wg sync.WaitGroup
+ stopDiscoveryCh := make(chan struct{})
+ ticker := time.NewTicker(period)
+
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for {
+ select {
+ case <-stopDiscoveryCh:
+ return
+ case <-ticker.C:
+ c.log.Debug("Auto discovering new partitions")
+ c.internalTopicSubscribeToPartitions()
+ }
+ }
+ }()
+
+ return func() {
+ ticker.Stop()
+ close(stopDiscoveryCh)
+ wg.Wait()
+ }
+}
+
+func (c *consumer) internalTopicSubscribeToPartitions() error {
+ partitions, err := c.client.TopicPartitions(c.topic)
+ if err != nil {
+ return err
+ }
+
+ oldNumPartitions := 0
+ newNumPartitions := len(partitions)
+
+ c.Lock()
+ defer c.Unlock()
+
+ oldConsumers := c.consumers
+ oldNumPartitions = len(oldConsumers)
+
+ if oldConsumers != nil {
+ if oldNumPartitions == newNumPartitions {
+ c.log.Debug("Number of partitions in topic has not changed")
+ return nil
+ }
+
+ c.log.WithField("old_partitions", oldNumPartitions).
+ WithField("new_partitions", newNumPartitions).
+ Info("Changed number of partitions in topic")
+ }
+
+ c.consumers = make([]*partitionConsumer, newNumPartitions)
+
+ // When for some reason (eg: forced deletion of sub partition) causes oldNumPartitions> newNumPartitions,
+ // we need to rebuild the cache of new consumers, otherwise the array will be out of bounds.
+ if oldConsumers != nil && oldNumPartitions < newNumPartitions {
+ // Copy over the existing consumer instances
+ for i := 0; i < oldNumPartitions; i++ {
+ c.consumers[i] = oldConsumers[i]
+ }
+ }
+
+ type ConsumerError struct {
+ err error
+ partition int
+ consumer *partitionConsumer
+ }
+
+ receiverQueueSize := c.options.ReceiverQueueSize
+ metadata := c.options.Properties
+ subProperties := c.options.SubscriptionProperties
+
+ startPartition := oldNumPartitions
+ partitionsToAdd := newNumPartitions - oldNumPartitions
+
+ if partitionsToAdd < 0 {
+ partitionsToAdd = newNumPartitions
+ startPartition = 0
+ }
+
+ var wg sync.WaitGroup
+ ch := make(chan ConsumerError, partitionsToAdd)
+ wg.Add(partitionsToAdd)
+
+ for partitionIdx := startPartition; partitionIdx < newNumPartitions; partitionIdx++ {
+ partitionTopic := partitions[partitionIdx]
+
+ go func(idx int, pt string) {
+ defer wg.Done()
+
+ var nackRedeliveryDelay time.Duration
+ if c.options.NackRedeliveryDelay == 0 {
+ nackRedeliveryDelay = defaultNackRedeliveryDelay
+ } else {
+ nackRedeliveryDelay = c.options.NackRedeliveryDelay
+ }
+ opts := &partitionConsumerOpts{
+ topic: pt,
+ consumerName: c.consumerName,
+ subscription: c.options.SubscriptionName,
+ subscriptionType: c.options.Type,
+ subscriptionInitPos: c.options.SubscriptionInitialPosition,
+ partitionIdx: idx,
+ receiverQueueSize: receiverQueueSize,
+ nackRedeliveryDelay: nackRedeliveryDelay,
+ nackBackoffPolicy: c.options.NackBackoffPolicy,
+ metadata: metadata,
+ subProperties: subProperties,
+ replicateSubscriptionState: c.options.ReplicateSubscriptionState,
+ startMessageID: nil,
+ subscriptionMode: durable,
+ readCompacted: c.options.ReadCompacted,
+ interceptors: c.options.Interceptors,
+ maxReconnectToBroker: c.options.MaxReconnectToBroker,
+ backoffPolicy: c.options.BackoffPolicy,
+ keySharedPolicy: c.options.KeySharedPolicy,
+ schema: c.options.Schema,
+ decryption: c.options.Decryption,
+ ackWithResponse: c.options.AckWithResponse,
+ maxPendingChunkedMessage: c.options.MaxPendingChunkedMessage,
+ expireTimeOfIncompleteChunk: c.options.ExpireTimeOfIncompleteChunk,
+ autoAckIncompleteChunk: c.options.AutoAckIncompleteChunk,
+ consumerEventListener: c.options.EventListener,
+ enableBatchIndexAck: c.options.EnableBatchIndexAcknowledgment,
+ ackGroupingOptions: c.options.AckGroupingOptions,
+ autoReceiverQueueSize: c.options.EnableAutoScaledReceiverQueueSize,
+ }
+ cons, err := newPartitionConsumer(c, c.client, opts, c.messageCh, c.dlq, c.metrics)
+ ch <- ConsumerError{
+ err: err,
+ partition: idx,
+ consumer: cons,
+ }
+ }(partitionIdx, partitionTopic)
+ }
+
+ go func() {
+ wg.Wait()
+ close(ch)
+ }()
+
+ for ce := range ch {
+ if ce.err != nil {
+ err = ce.err
+ } else {
+ c.consumers[ce.partition] = ce.consumer
+ }
+ }
+
+ if err != nil {
+ // Since there were some failures,
+ // cleanup all the partitions that succeeded in creating the consumer
+ for _, c := range c.consumers {
+ if c != nil {
+ c.Close()
+ }
+ }
+ return err
+ }
+
+ if newNumPartitions < oldNumPartitions {
+ c.metrics.ConsumersPartitions.Set(float64(newNumPartitions))
+ } else {
+ c.metrics.ConsumersPartitions.Add(float64(partitionsToAdd))
+ }
+ return nil
+}
+
+func (c *consumer) Subscription() string {
+ return c.options.SubscriptionName
+}
+
+func (c *consumer) Unsubscribe() error {
+ c.Lock()
+ defer c.Unlock()
+
+ var errMsg string
+ for _, consumer := range c.consumers {
+ if err := consumer.Unsubscribe(); err != nil {
+ errMsg += fmt.Sprintf("topic %s, subscription %s: %s", consumer.topic, c.Subscription(), err)
+ }
+ }
+ if errMsg != "" {
+ return fmt.Errorf(errMsg)
+ }
+ return nil
+}
+
+func (c *consumer) Receive(ctx context.Context) (message Message, err error) {
+ for {
+ select {
+ case <-c.closeCh:
+ return nil, newError(ConsumerClosed, "consumer closed")
+ case cm, ok := <-c.messageCh:
+ if !ok {
+ return nil, newError(ConsumerClosed, "consumer closed")
+ }
+ return cm.Message, nil
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+}
+
+// Chan return the message chan to users
+func (c *consumer) Chan() <-chan ConsumerMessage {
+ return c.messageCh
+}
+
+// Ack the consumption of a single message
+func (c *consumer) Ack(msg Message) error {
+ return c.AckID(msg.ID())
+}
+
+// AckID the consumption of a single message, identified by its MessageID
+func (c *consumer) AckID(msgID MessageID) error {
+ if err := c.checkMsgIDPartition(msgID); err != nil {
+ return err
+ }
+
+ if c.options.AckWithResponse {
+ return c.consumers[msgID.PartitionIdx()].AckIDWithResponse(msgID)
+ }
+
+ return c.consumers[msgID.PartitionIdx()].AckID(msgID)
+}
+
+// AckCumulative the reception of all the messages in the stream up to (and including)
+// the provided message, identified by its MessageID
+func (c *consumer) AckCumulative(msg Message) error {
+ return c.AckIDCumulative(msg.ID())
+}
+
+// AckIDCumulative the reception of all the messages in the stream up to (and including)
+// the provided message, identified by its MessageID
+func (c *consumer) AckIDCumulative(msgID MessageID) error {
+ if err := c.checkMsgIDPartition(msgID); err != nil {
+ return err
+ }
+
+ if c.options.AckWithResponse {
+ return c.consumers[msgID.PartitionIdx()].AckIDWithResponseCumulative(msgID)
+ }
+
+ return c.consumers[msgID.PartitionIdx()].AckIDCumulative(msgID)
+}
+
+// ReconsumeLater mark a message for redelivery after custom delay
+func (c *consumer) ReconsumeLater(msg Message, delay time.Duration) {
+ c.ReconsumeLaterWithCustomProperties(msg, map[string]string{}, delay)
+}
+
+// ReconsumeLaterWithCustomProperties mark a message for redelivery after custom delay with custom properties
+func (c *consumer) ReconsumeLaterWithCustomProperties(msg Message, customProperties map[string]string,
+ delay time.Duration) {
+ if delay < 0 {
+ delay = 0
+ }
+
+ if !checkMessageIDType(msg.ID()) {
+ c.log.Warnf("invalid message id type %T", msg.ID())
+ return
+ }
+
+ msgID := c.messageID(msg.ID())
+ if msgID == nil {
+ return
+ }
+
+ props := make(map[string]string)
+ for k, v := range msg.Properties() {
+ props[k] = v
+ }
+
+ for k, v := range customProperties {
+ props[k] = v
+ }
+
+ reconsumeTimes := 1
+ if s, ok := props[SysPropertyReconsumeTimes]; ok {
+ reconsumeTimes, _ = strconv.Atoi(s)
+ reconsumeTimes++
+ } else {
+ props[SysPropertyRealTopic] = msg.Topic()
+ props[SysPropertyOriginMessageID] = msgID.messageID.String()
+ }
+ props[SysPropertyReconsumeTimes] = strconv.Itoa(reconsumeTimes)
+ props[SysPropertyDelayTime] = fmt.Sprintf("%d", int64(delay)/1e6)
+
+ consumerMsg := ConsumerMessage{
+ Consumer: c,
+ Message: &message{
+ payLoad: msg.Payload(),
+ properties: props,
+ msgID: msgID,
+ },
+ }
+ if uint32(reconsumeTimes) > c.dlq.policy.MaxDeliveries {
+ c.dlq.Chan() <- consumerMsg
+ } else {
+ c.rlq.Chan() <- RetryMessage{
+ consumerMsg: consumerMsg,
+ producerMsg: ProducerMessage{
+ Payload: msg.Payload(),
+ Key: msg.Key(),
+ OrderingKey: msg.OrderingKey(),
+ Properties: props,
+ DeliverAfter: delay,
+ },
+ }
+ }
+}
+
+func (c *consumer) Nack(msg Message) {
+ if !checkMessageIDType(msg.ID()) {
+ c.log.Warnf("invalid message id type %T", msg.ID())
+ return
+ }
+ if c.options.EnableDefaultNackBackoffPolicy || c.options.NackBackoffPolicy != nil {
+ mid := c.messageID(msg.ID())
+ if mid == nil {
+ return
+ }
+
+ if mid.consumer != nil {
+ mid.NackByMsg(msg)
+ return
+ }
+ c.consumers[mid.partitionIdx].NackMsg(msg)
+ return
+ }
+
+ c.NackID(msg.ID())
+}
+
+func (c *consumer) NackID(msgID MessageID) {
+ if err := c.checkMsgIDPartition(msgID); err != nil {
+ return
+ }
+
+ c.consumers[msgID.PartitionIdx()].NackID(msgID)
+}
+
+func (c *consumer) Close() {
+ c.closeOnce.Do(func() {
+ c.stopDiscovery()
+
+ c.Lock()
+ defer c.Unlock()
+
+ var wg sync.WaitGroup
+ for i := range c.consumers {
+ wg.Add(1)
+ go func(pc *partitionConsumer) {
+ defer wg.Done()
+ pc.Close()
+ }(c.consumers[i])
+ }
+ wg.Wait()
+ close(c.closeCh)
+ c.client.handlers.Del(c)
+ c.dlq.close()
+ c.rlq.close()
+ c.metrics.ConsumersClosed.Inc()
+ c.metrics.ConsumersPartitions.Sub(float64(len(c.consumers)))
+ })
+}
+
+func (c *consumer) Seek(msgID MessageID) error {
+ c.Lock()
+ defer c.Unlock()
+
+ if len(c.consumers) > 1 {
+ return newError(SeekFailed, "for partition topic, seek command should perform on the individual partitions")
+ }
+
+ if err := c.checkMsgIDPartition(msgID); err != nil {
+ return err
+ }
+
+ if err := c.consumers[msgID.PartitionIdx()].Seek(msgID); err != nil {
+ return err
+ }
+
+ // clear messageCh
+ for len(c.messageCh) > 0 {
+ <-c.messageCh
+ }
+
+ return nil
+}
+
+func (c *consumer) SeekByTime(time time.Time) error {
+ c.Lock()
+ defer c.Unlock()
+ var errs error
+ // run SeekByTime on every partition of topic
+ for _, cons := range c.consumers {
+ if err := cons.SeekByTime(time); err != nil {
+ msg := fmt.Sprintf("unable to SeekByTime for topic=%s subscription=%s", c.topic, c.Subscription())
+ errs = pkgerrors.Wrap(newError(SeekFailed, err.Error()), msg)
+ }
+ }
+
+ // clear messageCh
+ for len(c.messageCh) > 0 {
+ <-c.messageCh
+ }
+
+ return errs
+}
+
+func (c *consumer) checkMsgIDPartition(msgID MessageID) error {
+ partition := msgID.PartitionIdx()
+ if partition < 0 || int(partition) >= len(c.consumers) {
+ c.log.Errorf("invalid partition index %d expected a partition between [0-%d]",
+ partition, len(c.consumers))
+ return fmt.Errorf("invalid partition index %d expected a partition between [0-%d]",
+ partition, len(c.consumers))
+ }
+ return nil
+}
+
+var r = &random{
+ R: rand.New(rand.NewSource(time.Now().UnixNano())),
+}
+
+type random struct {
+ sync.Mutex
+ R *rand.Rand
+}
+
+func generateRandomName() string {
+ r.Lock()
+ defer r.Unlock()
+ chars := "abcdefghijklmnopqrstuvwxyz"
+ bytes := make([]byte, 5)
+ for i := range bytes {
+ bytes[i] = chars[r.R.Intn(len(chars))]
+ }
+ return string(bytes)
+}
+
+func distinct(fqdnTopics []string) []string {
+ set := make(map[string]struct{})
+ uniques := make([]string, 0, len(fqdnTopics))
+ for _, topic := range fqdnTopics {
+ if _, ok := set[topic]; !ok {
+ set[topic] = struct{}{}
+ uniques = append(uniques, topic)
+ }
+ }
+ return uniques
+}
+
+func toProtoSubType(st SubscriptionType) pb.CommandSubscribe_SubType {
+ switch st {
+ case Exclusive:
+ return pb.CommandSubscribe_Exclusive
+ case Shared:
+ return pb.CommandSubscribe_Shared
+ case Failover:
+ return pb.CommandSubscribe_Failover
+ case KeyShared:
+ return pb.CommandSubscribe_Key_Shared
+ }
+
+ return pb.CommandSubscribe_Exclusive
+}
+
+func toProtoInitialPosition(p SubscriptionInitialPosition) pb.CommandSubscribe_InitialPosition {
+ switch p {
+ case SubscriptionPositionLatest:
+ return pb.CommandSubscribe_Latest
+ case SubscriptionPositionEarliest:
+ return pb.CommandSubscribe_Earliest
+ }
+
+ return pb.CommandSubscribe_Latest
+}
+
+func (c *consumer) messageID(msgID MessageID) *trackingMessageID {
+ mid := toTrackingMessageID(msgID)
+
+ partition := int(mid.partitionIdx)
+ // did we receive a valid partition index?
+ if partition < 0 || partition >= len(c.consumers) {
+ c.log.Warnf("invalid partition index %d expected a partition between [0-%d]",
+ partition, len(c.consumers))
+ return nil
+ }
+
+ return mid
+}
+
+func addMessageCryptoIfMissing(client *client, options *ConsumerOptions, topics interface{}) error {
+ // decryption is enabled, use default messagecrypto if not provided
+ if options.Decryption != nil && options.Decryption.MessageCrypto == nil {
+ messageCrypto, err := crypto.NewDefaultMessageCrypto("decrypt",
+ false,
+ client.log.SubLogger(log.Fields{"topic": topics}))
+ if err != nil {
+ return err
+ }
+ options.Decryption.MessageCrypto = messageCrypto
+ }
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_interceptor.go b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_interceptor.go
new file mode 100644
index 00000000..db46b784
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_interceptor.go
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+type ConsumerInterceptor interface {
+ // BeforeConsume This is called just before the message is send to Consumer's ConsumerMessage channel.
+ BeforeConsume(message ConsumerMessage)
+
+ // OnAcknowledge This is called consumer sends the acknowledgment to the broker.
+ OnAcknowledge(consumer Consumer, msgID MessageID)
+
+ // OnNegativeAcksSend This method will be called when a redelivery from a negative acknowledge occurs.
+ OnNegativeAcksSend(consumer Consumer, msgIDs []MessageID)
+}
+
+type ConsumerInterceptors []ConsumerInterceptor
+
+func (x ConsumerInterceptors) BeforeConsume(message ConsumerMessage) {
+ for i := range x {
+ x[i].BeforeConsume(message)
+ }
+}
+
+func (x ConsumerInterceptors) OnAcknowledge(consumer Consumer, msgID MessageID) {
+ for i := range x {
+ x[i].OnAcknowledge(consumer, msgID)
+ }
+}
+
+func (x ConsumerInterceptors) OnNegativeAcksSend(consumer Consumer, msgIDs []MessageID) {
+ for i := range x {
+ x[i].OnNegativeAcksSend(consumer, msgIDs)
+ }
+}
+
+var defaultConsumerInterceptors = make(ConsumerInterceptors, 0)
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_multitopic.go b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_multitopic.go
new file mode 100644
index 00000000..8108c294
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_multitopic.go
@@ -0,0 +1,267 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ pkgerrors "github.com/pkg/errors"
+
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+type multiTopicConsumer struct {
+ client *client
+
+ options ConsumerOptions
+
+ consumerName string
+ messageCh chan ConsumerMessage
+
+ consumers map[string]Consumer
+
+ dlq *dlqRouter
+ rlq *retryRouter
+ closeOnce sync.Once
+ closeCh chan struct{}
+
+ log log.Logger
+}
+
+func newMultiTopicConsumer(client *client, options ConsumerOptions, topics []string,
+ messageCh chan ConsumerMessage, dlq *dlqRouter, rlq *retryRouter) (Consumer, error) {
+ mtc := &multiTopicConsumer{
+ client: client,
+ options: options,
+ messageCh: messageCh,
+ consumers: make(map[string]Consumer, len(topics)),
+ closeCh: make(chan struct{}),
+ dlq: dlq,
+ rlq: rlq,
+ log: client.log.SubLogger(log.Fields{"topic": topics}),
+ consumerName: options.Name,
+ }
+
+ var errs error
+ for ce := range subscriber(client, topics, options, messageCh, dlq, rlq) {
+ if ce.err != nil {
+ errs = pkgerrors.Wrapf(ce.err, "unable to subscribe to topic=%s", ce.topic)
+ } else {
+ mtc.consumers[ce.topic] = ce.consumer
+ }
+ }
+
+ if errs != nil {
+ for _, c := range mtc.consumers {
+ c.Close()
+ }
+ return nil, errs
+ }
+
+ return mtc, nil
+}
+
+func (c *multiTopicConsumer) Subscription() string {
+ return c.options.SubscriptionName
+}
+
+func (c *multiTopicConsumer) Unsubscribe() error {
+ var errs error
+ for t, consumer := range c.consumers {
+ if err := consumer.Unsubscribe(); err != nil {
+ msg := fmt.Sprintf("unable to unsubscribe from topic=%s subscription=%s",
+ t, c.Subscription())
+ errs = pkgerrors.Wrap(err, msg)
+ }
+ }
+ return errs
+}
+
+func (c *multiTopicConsumer) Receive(ctx context.Context) (message Message, err error) {
+ for {
+ select {
+ case <-c.closeCh:
+ return nil, newError(ConsumerClosed, "consumer closed")
+ case cm, ok := <-c.messageCh:
+ if !ok {
+ return nil, newError(ConsumerClosed, "consumer closed")
+ }
+ return cm.Message, nil
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+}
+
+// Chan return the message chan to users
+func (c *multiTopicConsumer) Chan() <-chan ConsumerMessage {
+ return c.messageCh
+}
+
+// Ack the consumption of a single message
+func (c *multiTopicConsumer) Ack(msg Message) error {
+ return c.AckID(msg.ID())
+}
+
+// AckID the consumption of a single message, identified by its MessageID
+func (c *multiTopicConsumer) AckID(msgID MessageID) error {
+ if !checkMessageIDType(msgID) {
+ c.log.Warnf("invalid message id type %T", msgID)
+ return errors.New("invalid message id type in multi_consumer")
+ }
+ mid := toTrackingMessageID(msgID)
+
+ if mid.consumer == nil {
+ c.log.Warnf("unable to ack messageID=%+v can not determine topic", msgID)
+ return errors.New("unable to ack message because consumer is nil")
+ }
+
+ if c.options.AckWithResponse {
+ return mid.consumer.AckIDWithResponse(msgID)
+ }
+
+ return mid.consumer.AckID(msgID)
+}
+
+// AckCumulative the reception of all the messages in the stream up to (and including)
+// the provided message
+func (c *multiTopicConsumer) AckCumulative(msg Message) error {
+ return c.AckIDCumulative(msg.ID())
+}
+
+// AckIDCumulative the reception of all the messages in the stream up to (and including)
+// the provided message, identified by its MessageID
+func (c *multiTopicConsumer) AckIDCumulative(msgID MessageID) error {
+ if !checkMessageIDType(msgID) {
+ c.log.Warnf("invalid message id type %T", msgID)
+ return errors.New("invalid message id type in multi_consumer")
+ }
+ mid := toTrackingMessageID(msgID)
+
+ if mid.consumer == nil {
+ c.log.Warnf("unable to ack messageID=%+v can not determine topic", msgID)
+ return errors.New("unable to ack message because consumer is nil")
+ }
+
+ if c.options.AckWithResponse {
+ return mid.consumer.AckIDWithResponseCumulative(msgID)
+ }
+
+ return mid.consumer.AckIDCumulative(msgID)
+}
+
+func (c *multiTopicConsumer) ReconsumeLater(msg Message, delay time.Duration) {
+ c.ReconsumeLaterWithCustomProperties(msg, map[string]string{}, delay)
+}
+
+func (c *multiTopicConsumer) ReconsumeLaterWithCustomProperties(msg Message, customProperties map[string]string,
+ delay time.Duration) {
+ names, err := validateTopicNames(msg.Topic())
+ if err != nil {
+ c.log.Errorf("validate msg topic %q failed: %v", msg.Topic(), err)
+ return
+ }
+ if len(names) != 1 {
+ c.log.Errorf("invalid msg topic %q names: %+v ", msg.Topic(), names)
+ return
+ }
+
+ tn := names[0]
+ fqdnTopic := internal.TopicNameWithoutPartitionPart(tn)
+ consumer, ok := c.consumers[fqdnTopic]
+ if !ok {
+ // check to see if the topic with the partition part is in the consumers
+ // this can happen when the consumer is configured to consume from a specific partition
+ if consumer, ok = c.consumers[tn.Name]; !ok {
+ c.log.Warnf("consumer of topic %s not exist unexpectedly", msg.Topic())
+ return
+ }
+ }
+ consumer.ReconsumeLaterWithCustomProperties(msg, customProperties, delay)
+}
+
+func (c *multiTopicConsumer) Nack(msg Message) {
+ if c.options.EnableDefaultNackBackoffPolicy || c.options.NackBackoffPolicy != nil {
+ msgID := msg.ID()
+ if !checkMessageIDType(msgID) {
+ c.log.Warnf("invalid message id type %T", msgID)
+ return
+ }
+ mid := toTrackingMessageID(msgID)
+
+ if mid.consumer == nil {
+ c.log.Warnf("unable to nack messageID=%+v can not determine topic", msgID)
+ return
+ }
+ mid.NackByMsg(msg)
+ return
+ }
+
+ c.NackID(msg.ID())
+}
+
+func (c *multiTopicConsumer) NackID(msgID MessageID) {
+ if !checkMessageIDType(msgID) {
+ c.log.Warnf("invalid message id type %T", msgID)
+ return
+ }
+ mid := toTrackingMessageID(msgID)
+
+ if mid.consumer == nil {
+ c.log.Warnf("unable to nack messageID=%+v can not determine topic", msgID)
+ return
+ }
+
+ mid.consumer.NackID(msgID)
+}
+
+func (c *multiTopicConsumer) Close() {
+ c.closeOnce.Do(func() {
+ var wg sync.WaitGroup
+ wg.Add(len(c.consumers))
+ for _, con := range c.consumers {
+ go func(consumer Consumer) {
+ defer wg.Done()
+ consumer.Close()
+ }(con)
+ }
+ wg.Wait()
+ close(c.closeCh)
+ c.client.handlers.Del(c)
+ c.dlq.close()
+ c.rlq.close()
+ })
+}
+
+func (c *multiTopicConsumer) Seek(msgID MessageID) error {
+ return newError(SeekFailed, "seek command not allowed for multi topic consumer")
+}
+
+func (c *multiTopicConsumer) SeekByTime(time time.Time) error {
+ return newError(SeekFailed, "seek command not allowed for multi topic consumer")
+}
+
+// Name returns the name of consumer.
+func (c *multiTopicConsumer) Name() string {
+ return c.consumerName
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_partition.go b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_partition.go
new file mode 100644
index 00000000..fb77d0dc
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_partition.go
@@ -0,0 +1,2129 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "container/list"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "math"
+ "strings"
+ "sync"
+ "time"
+
+ "google.golang.org/protobuf/proto"
+
+ "github.com/apache/pulsar-client-go/pulsar/crypto"
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ "github.com/apache/pulsar-client-go/pulsar/internal/compression"
+ cryptointernal "github.com/apache/pulsar-client-go/pulsar/internal/crypto"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+ "github.com/bits-and-blooms/bitset"
+
+ uAtomic "go.uber.org/atomic"
+)
+
+type consumerState int
+
+const (
+ // consumer states
+ consumerInit = iota
+ consumerReady
+ consumerClosing
+ consumerClosed
+)
+
+func (s consumerState) String() string {
+ switch s {
+ case consumerInit:
+ return "Initializing"
+ case consumerReady:
+ return "Ready"
+ case consumerClosing:
+ return "Closing"
+ case consumerClosed:
+ return "Closed"
+ default:
+ return "Unknown"
+ }
+}
+
+type subscriptionMode int
+
+const (
+ // Make the subscription to be backed by a durable cursor that will retain messages and persist the current
+ // position
+ durable subscriptionMode = iota
+
+ // Lightweight subscription mode that doesn't have a durable cursor associated
+ nonDurable
+)
+
+const (
+ initialReceiverQueueSize = 1
+ receiverQueueExpansionMemThreshold = 0.75
+)
+
+const (
+ noMessageEntry = -1
+)
+
+type partitionConsumerOpts struct {
+ topic string
+ consumerName string
+ subscription string
+ subscriptionType SubscriptionType
+ subscriptionInitPos SubscriptionInitialPosition
+ partitionIdx int
+ receiverQueueSize int
+ autoReceiverQueueSize bool
+ nackRedeliveryDelay time.Duration
+ nackBackoffPolicy NackBackoffPolicy
+ metadata map[string]string
+ subProperties map[string]string
+ replicateSubscriptionState bool
+ startMessageID *trackingMessageID
+ startMessageIDInclusive bool
+ subscriptionMode subscriptionMode
+ readCompacted bool
+ disableForceTopicCreation bool
+ interceptors ConsumerInterceptors
+ maxReconnectToBroker *uint
+ backoffPolicy internal.BackoffPolicy
+ keySharedPolicy *KeySharedPolicy
+ schema Schema
+ decryption *MessageDecryptionInfo
+ ackWithResponse bool
+ maxPendingChunkedMessage int
+ expireTimeOfIncompleteChunk time.Duration
+ autoAckIncompleteChunk bool
+ // in failover mode, this callback will be called when consumer change
+ consumerEventListener ConsumerEventListener
+ enableBatchIndexAck bool
+ ackGroupingOptions *AckGroupingOptions
+}
+
+type ConsumerEventListener interface {
+ BecameActive(consumer Consumer, topicName string, partition int32)
+ BecameInactive(consumer Consumer, topicName string, partition int32)
+}
+
+type partitionConsumer struct {
+ client *client
+
+ // this is needed for sending ConsumerMessage on the messageCh
+ parentConsumer Consumer
+ state uAtomic.Int32
+ options *partitionConsumerOpts
+
+ conn uAtomic.Value
+
+ topic string
+ name string
+ consumerID uint64
+ partitionIdx int32
+
+ // shared channel
+ messageCh chan ConsumerMessage
+
+ // the number of message slots available
+ availablePermits *availablePermits
+
+ // the size of the queue channel for buffering messages
+ maxQueueSize int32
+ queueCh chan []*message
+ startMessageID atomicMessageID
+ lastDequeuedMsg *trackingMessageID
+
+ currentQueueSize uAtomic.Int32
+ scaleReceiverQueueHint uAtomic.Bool
+ incomingMessages uAtomic.Int32
+
+ eventsCh chan interface{}
+ connectedCh chan struct{}
+ connectClosedCh chan connectionClosed
+ closeCh chan struct{}
+ clearQueueCh chan func(id *trackingMessageID)
+
+ nackTracker *negativeAcksTracker
+ dlq *dlqRouter
+
+ log log.Logger
+ compressionProviders sync.Map //map[pb.CompressionType]compression.Provider
+ metrics *internal.LeveledMetrics
+ decryptor cryptointernal.Decryptor
+ schemaInfoCache *schemaInfoCache
+
+ chunkedMsgCtxMap *chunkedMsgCtxMap
+ unAckChunksTracker *unAckChunksTracker
+ ackGroupingTracker ackGroupingTracker
+}
+
+func (pc *partitionConsumer) ActiveConsumerChanged(isActive bool) {
+ listener := pc.options.consumerEventListener
+ if listener == nil {
+ // didn't set a listener
+ return
+ }
+ if isActive {
+ listener.BecameActive(pc.parentConsumer, pc.topic, pc.partitionIdx)
+ } else {
+ listener.BecameInactive(pc.parentConsumer, pc.topic, pc.partitionIdx)
+ }
+}
+
+type availablePermits struct {
+ permits uAtomic.Int32
+ pc *partitionConsumer
+}
+
+func (p *availablePermits) inc() {
+ // atomic add availablePermits
+ p.add(1)
+}
+
+func (p *availablePermits) add(delta int32) {
+ p.permits.Add(delta)
+ p.flowIfNeed()
+}
+
+func (p *availablePermits) reset() {
+ p.permits.Store(0)
+}
+
+func (p *availablePermits) get() int32 {
+ return p.permits.Load()
+}
+
+func (p *availablePermits) flowIfNeed() {
+ // TODO implement a better flow controller
+ // send more permits if needed
+ var flowThreshold int32
+ if p.pc.options.autoReceiverQueueSize {
+ flowThreshold = int32(math.Max(float64(p.pc.currentQueueSize.Load()/2), 1))
+ } else {
+ flowThreshold = int32(math.Max(float64(p.pc.maxQueueSize/2), 1))
+ }
+
+ current := p.get()
+ if current >= flowThreshold {
+ availablePermits := current
+ requestedPermits := current
+ // check if permits changed
+ if !p.permits.CAS(current, 0) {
+ return
+ }
+
+ p.pc.log.Debugf("requesting more permits=%d available=%d", requestedPermits, availablePermits)
+ if err := p.pc.internalFlow(uint32(requestedPermits)); err != nil {
+ p.pc.log.WithError(err).Error("unable to send permits")
+ }
+ }
+}
+
+// atomicMessageID is a wrapper for trackingMessageID to make get and set atomic
+type atomicMessageID struct {
+ msgID *trackingMessageID
+ sync.RWMutex
+}
+
+func (a *atomicMessageID) get() *trackingMessageID {
+ a.RLock()
+ defer a.RUnlock()
+ return a.msgID
+}
+
+func (a *atomicMessageID) set(msgID *trackingMessageID) {
+ a.Lock()
+ defer a.Unlock()
+ a.msgID = msgID
+}
+
+type schemaInfoCache struct {
+ lock sync.RWMutex
+ cache map[string]Schema
+ client *client
+ topic string
+}
+
+func newSchemaInfoCache(client *client, topic string) *schemaInfoCache {
+ return &schemaInfoCache{
+ cache: make(map[string]Schema),
+ client: client,
+ topic: topic,
+ }
+}
+
+func (s *schemaInfoCache) Get(schemaVersion []byte) (schema Schema, err error) {
+ key := hex.EncodeToString(schemaVersion)
+ s.lock.RLock()
+ schema, ok := s.cache[key]
+ s.lock.RUnlock()
+ if ok {
+ return schema, nil
+ }
+
+ pbSchema, err := s.client.lookupService.GetSchema(s.topic, schemaVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ if pbSchema == nil {
+ err = fmt.Errorf("schema not found for topic: [ %v ], schema version : [ %v ]", s.topic, schemaVersion)
+ return nil, err
+ }
+
+ var properties = internal.ConvertToStringMap(pbSchema.Properties)
+
+ schema, err = NewSchema(SchemaType(*pbSchema.Type), pbSchema.SchemaData, properties)
+ if err != nil {
+ return nil, err
+ }
+ s.add(key, schema)
+ return schema, nil
+}
+
+func (s *schemaInfoCache) add(schemaVersionHash string, schema Schema) {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+
+ s.cache[schemaVersionHash] = schema
+}
+
+func newPartitionConsumer(parent Consumer, client *client, options *partitionConsumerOpts,
+ messageCh chan ConsumerMessage, dlq *dlqRouter,
+ metrics *internal.LeveledMetrics) (*partitionConsumer, error) {
+ pc := &partitionConsumer{
+ parentConsumer: parent,
+ client: client,
+ options: options,
+ topic: options.topic,
+ name: options.consumerName,
+ consumerID: client.rpcClient.NewConsumerID(),
+ partitionIdx: int32(options.partitionIdx),
+ eventsCh: make(chan interface{}, 10),
+ maxQueueSize: int32(options.receiverQueueSize),
+ queueCh: make(chan []*message, options.receiverQueueSize),
+ startMessageID: atomicMessageID{msgID: options.startMessageID},
+ connectedCh: make(chan struct{}),
+ messageCh: messageCh,
+ connectClosedCh: make(chan connectionClosed, 10),
+ closeCh: make(chan struct{}),
+ clearQueueCh: make(chan func(id *trackingMessageID)),
+ compressionProviders: sync.Map{},
+ dlq: dlq,
+ metrics: metrics,
+ schemaInfoCache: newSchemaInfoCache(client, options.topic),
+ }
+ if pc.options.autoReceiverQueueSize {
+ pc.currentQueueSize.Store(initialReceiverQueueSize)
+ pc.client.memLimit.RegisterTrigger(pc.shrinkReceiverQueueSize)
+ } else {
+ pc.currentQueueSize.Store(int32(pc.options.receiverQueueSize))
+ }
+ pc.availablePermits = &availablePermits{pc: pc}
+ pc.chunkedMsgCtxMap = newChunkedMsgCtxMap(options.maxPendingChunkedMessage, pc)
+ pc.unAckChunksTracker = newUnAckChunksTracker(pc)
+ pc.ackGroupingTracker = newAckGroupingTracker(options.ackGroupingOptions,
+ func(id MessageID) { pc.sendIndividualAck(id) },
+ func(id MessageID) { pc.sendCumulativeAck(id) },
+ func(ids []*pb.MessageIdData) { pc.eventsCh <- ids })
+ pc.setConsumerState(consumerInit)
+ pc.log = client.log.SubLogger(log.Fields{
+ "name": pc.name,
+ "topic": options.topic,
+ "subscription": options.subscription,
+ "consumerID": pc.consumerID,
+ })
+
+ var decryptor cryptointernal.Decryptor
+ if pc.options.decryption == nil {
+ decryptor = cryptointernal.NewNoopDecryptor() // default to noopDecryptor
+ } else {
+ decryptor = cryptointernal.NewConsumerDecryptor(
+ options.decryption.KeyReader,
+ options.decryption.MessageCrypto,
+ pc.log,
+ )
+ }
+
+ pc.decryptor = decryptor
+
+ pc.nackTracker = newNegativeAcksTracker(pc, options.nackRedeliveryDelay, options.nackBackoffPolicy, pc.log)
+
+ err := pc.grabConn()
+ if err != nil {
+ pc.log.WithError(err).Error("Failed to create consumer")
+ pc.nackTracker.Close()
+ return nil, err
+ }
+ pc.log.Info("Created consumer")
+ pc.setConsumerState(consumerReady)
+
+ startingMessageID := pc.startMessageID.get()
+ if pc.options.startMessageIDInclusive && startingMessageID != nil && startingMessageID.equal(latestMessageID) {
+ msgID, err := pc.requestGetLastMessageID()
+ if err != nil {
+ pc.nackTracker.Close()
+ return nil, err
+ }
+ if msgID.entryID != noMessageEntry {
+ pc.startMessageID.set(msgID)
+
+ // use the WithoutClear version because the dispatcher is not started yet
+ err = pc.requestSeekWithoutClear(msgID.messageID)
+ if err != nil {
+ pc.nackTracker.Close()
+ return nil, err
+ }
+ }
+ }
+
+ go pc.dispatcher()
+
+ go pc.runEventsLoop()
+
+ return pc, nil
+}
+
+func (pc *partitionConsumer) Unsubscribe() error {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to unsubscribe closing or closed consumer")
+ return nil
+ }
+
+ req := &unsubscribeRequest{doneCh: make(chan struct{})}
+ pc.eventsCh <- req
+
+ // wait for the request to complete
+ <-req.doneCh
+ return req.err
+}
+
+func (pc *partitionConsumer) internalUnsubscribe(unsub *unsubscribeRequest) {
+ defer close(unsub.doneCh)
+
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to unsubscribe closing or closed consumer")
+ return
+ }
+
+ pc.setConsumerState(consumerClosing)
+ requestID := pc.client.rpcClient.NewRequestID()
+ cmdUnsubscribe := &pb.CommandUnsubscribe{
+ RequestId: proto.Uint64(requestID),
+ ConsumerId: proto.Uint64(pc.consumerID),
+ }
+ _, err := pc.client.rpcClient.RequestOnCnx(pc._getConn(), requestID, pb.BaseCommand_UNSUBSCRIBE, cmdUnsubscribe)
+ if err != nil {
+ pc.log.WithError(err).Error("Failed to unsubscribe consumer")
+ unsub.err = err
+ // Set the state to ready for closing the consumer
+ pc.setConsumerState(consumerReady)
+ // Should'nt remove the consumer handler
+ return
+ }
+
+ pc._getConn().DeleteConsumeHandler(pc.consumerID)
+ if pc.nackTracker != nil {
+ pc.nackTracker.Close()
+ }
+ pc.log.Infof("The consumer[%d] successfully unsubscribed", pc.consumerID)
+ pc.setConsumerState(consumerClosed)
+}
+
+func (pc *partitionConsumer) getLastMessageID() (*trackingMessageID, error) {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to redeliver closing or closed consumer")
+ return nil, errors.New("failed to redeliver closing or closed consumer")
+ }
+ req := &getLastMsgIDRequest{doneCh: make(chan struct{})}
+ pc.eventsCh <- req
+
+ // wait for the request to complete
+ <-req.doneCh
+ return req.msgID, req.err
+}
+
+func (pc *partitionConsumer) internalGetLastMessageID(req *getLastMsgIDRequest) {
+ defer close(req.doneCh)
+ req.msgID, req.err = pc.requestGetLastMessageID()
+}
+
+func (pc *partitionConsumer) requestGetLastMessageID() (*trackingMessageID, error) {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to getLastMessageID closing or closed consumer")
+ return nil, errors.New("failed to getLastMessageID closing or closed consumer")
+ }
+
+ requestID := pc.client.rpcClient.NewRequestID()
+ cmdGetLastMessageID := &pb.CommandGetLastMessageId{
+ RequestId: proto.Uint64(requestID),
+ ConsumerId: proto.Uint64(pc.consumerID),
+ }
+ res, err := pc.client.rpcClient.RequestOnCnx(pc._getConn(), requestID,
+ pb.BaseCommand_GET_LAST_MESSAGE_ID, cmdGetLastMessageID)
+ if err != nil {
+ pc.log.WithError(err).Error("Failed to get last message id")
+ return nil, err
+ }
+ id := res.Response.GetLastMessageIdResponse.GetLastMessageId()
+ return convertToMessageID(id), nil
+}
+
+func (pc *partitionConsumer) ackID(msgID MessageID, withResponse bool) error {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to ack by closing or closed consumer")
+ return errors.New("consumer state is closed")
+ }
+
+ if cmid, ok := msgID.(*chunkMessageID); ok {
+ return pc.unAckChunksTracker.ack(cmid)
+ }
+
+ trackingID := toTrackingMessageID(msgID)
+
+ if trackingID != nil && trackingID.ack() {
+ // All messages in the same batch have been acknowledged, we only need to acknowledge the
+ // MessageID that represents the entry that stores the whole batch
+ trackingID = &trackingMessageID{
+ messageID: &messageID{
+ ledgerID: trackingID.ledgerID,
+ entryID: trackingID.entryID,
+ },
+ }
+ pc.metrics.AcksCounter.Inc()
+ pc.metrics.ProcessingTime.Observe(float64(time.Now().UnixNano()-trackingID.receivedTime.UnixNano()) / 1.0e9)
+ } else if !pc.options.enableBatchIndexAck {
+ return nil
+ }
+
+ var ackReq *ackRequest
+ if withResponse {
+ ackReq := pc.sendIndividualAck(trackingID)
+ <-ackReq.doneCh
+ } else {
+ pc.ackGroupingTracker.add(trackingID)
+ }
+ pc.options.interceptors.OnAcknowledge(pc.parentConsumer, msgID)
+ if ackReq == nil {
+ return nil
+ }
+ return ackReq.err
+}
+
+func (pc *partitionConsumer) sendIndividualAck(msgID MessageID) *ackRequest {
+ ackReq := &ackRequest{
+ doneCh: make(chan struct{}),
+ ackType: individualAck,
+ msgID: *msgID.(*trackingMessageID),
+ }
+ pc.eventsCh <- ackReq
+ return ackReq
+}
+
+func (pc *partitionConsumer) AckIDWithResponse(msgID MessageID) error {
+ if !checkMessageIDType(msgID) {
+ pc.log.Errorf("invalid message id type %T", msgID)
+ return fmt.Errorf("invalid message id type %T", msgID)
+ }
+ return pc.ackID(msgID, true)
+}
+
+func (pc *partitionConsumer) AckID(msgID MessageID) error {
+ if !checkMessageIDType(msgID) {
+ pc.log.Errorf("invalid message id type %T", msgID)
+ return fmt.Errorf("invalid message id type %T", msgID)
+ }
+ return pc.ackID(msgID, false)
+}
+
+func (pc *partitionConsumer) AckIDCumulative(msgID MessageID) error {
+ if !checkMessageIDType(msgID) {
+ pc.log.Errorf("invalid message id type %T", msgID)
+ return fmt.Errorf("invalid message id type %T", msgID)
+ }
+ return pc.internalAckIDCumulative(msgID, false)
+}
+
+func (pc *partitionConsumer) AckIDWithResponseCumulative(msgID MessageID) error {
+ if !checkMessageIDType(msgID) {
+ pc.log.Errorf("invalid message id type %T", msgID)
+ return fmt.Errorf("invalid message id type %T", msgID)
+ }
+ return pc.internalAckIDCumulative(msgID, true)
+}
+
+func (pc *partitionConsumer) internalAckIDCumulative(msgID MessageID, withResponse bool) error {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to ack by closing or closed consumer")
+ return errors.New("consumer state is closed")
+ }
+
+ // chunk message id will be converted to tracking message id
+ trackingID := toTrackingMessageID(msgID)
+ if trackingID == nil {
+ return errors.New("failed to convert trackingMessageID")
+ }
+
+ var msgIDToAck *trackingMessageID
+ if trackingID.ackCumulative() || pc.options.enableBatchIndexAck {
+ msgIDToAck = trackingID
+ } else if !trackingID.tracker.hasPrevBatchAcked() {
+ // get previous batch message id
+ msgIDToAck = trackingID.prev()
+ trackingID.tracker.setPrevBatchAcked()
+ } else {
+ // waiting for all the msgs are acked in this batch
+ return nil
+ }
+
+ pc.metrics.AcksCounter.Inc()
+ pc.metrics.ProcessingTime.Observe(float64(time.Now().UnixNano()-trackingID.receivedTime.UnixNano()) / 1.0e9)
+
+ var ackReq *ackRequest
+ if withResponse {
+ ackReq := pc.sendCumulativeAck(msgIDToAck)
+ <-ackReq.doneCh
+ } else {
+ pc.ackGroupingTracker.addCumulative(msgIDToAck)
+ }
+
+ pc.options.interceptors.OnAcknowledge(pc.parentConsumer, msgID)
+
+ if cmid, ok := msgID.(*chunkMessageID); ok {
+ pc.unAckChunksTracker.remove(cmid)
+ }
+
+ if ackReq == nil {
+ return nil
+ }
+ return ackReq.err
+}
+
+func (pc *partitionConsumer) sendCumulativeAck(msgID MessageID) *ackRequest {
+ ackReq := &ackRequest{
+ doneCh: make(chan struct{}),
+ ackType: cumulativeAck,
+ msgID: *msgID.(*trackingMessageID),
+ }
+ pc.eventsCh <- ackReq
+ return ackReq
+}
+
+func (pc *partitionConsumer) NackID(msgID MessageID) {
+ if !checkMessageIDType(msgID) {
+ pc.log.Warnf("invalid message id type %T", msgID)
+ return
+ }
+
+ if cmid, ok := msgID.(*chunkMessageID); ok {
+ pc.unAckChunksTracker.nack(cmid)
+ return
+ }
+
+ trackingID := toTrackingMessageID(msgID)
+
+ pc.nackTracker.Add(trackingID.messageID)
+ pc.metrics.NacksCounter.Inc()
+}
+
+func (pc *partitionConsumer) NackMsg(msg Message) {
+ pc.nackTracker.AddMessage(msg)
+ pc.metrics.NacksCounter.Inc()
+}
+
+func (pc *partitionConsumer) Redeliver(msgIds []messageID) {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to redeliver closing or closed consumer")
+ return
+ }
+ pc.eventsCh <- &redeliveryRequest{msgIds}
+
+ iMsgIds := make([]MessageID, len(msgIds))
+ for i := range iMsgIds {
+ iMsgIds[i] = &msgIds[i]
+ }
+ pc.options.interceptors.OnNegativeAcksSend(pc.parentConsumer, iMsgIds)
+}
+
+func (pc *partitionConsumer) internalRedeliver(req *redeliveryRequest) {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to redeliver closing or closed consumer")
+ return
+ }
+ msgIds := req.msgIds
+ pc.log.Debug("Request redelivery after negative ack for messages", msgIds)
+
+ msgIDDataList := make([]*pb.MessageIdData, len(msgIds))
+ for i := 0; i < len(msgIds); i++ {
+ msgIDDataList[i] = &pb.MessageIdData{
+ LedgerId: proto.Uint64(uint64(msgIds[i].ledgerID)),
+ EntryId: proto.Uint64(uint64(msgIds[i].entryID)),
+ }
+ }
+
+ err := pc.client.rpcClient.RequestOnCnxNoWait(pc._getConn(),
+ pb.BaseCommand_REDELIVER_UNACKNOWLEDGED_MESSAGES, &pb.CommandRedeliverUnacknowledgedMessages{
+ ConsumerId: proto.Uint64(pc.consumerID),
+ MessageIds: msgIDDataList,
+ })
+ if err != nil {
+ pc.log.Error("Connection was closed when request redeliver cmd")
+ }
+}
+
+func (pc *partitionConsumer) getConsumerState() consumerState {
+ return consumerState(pc.state.Load())
+}
+
+func (pc *partitionConsumer) setConsumerState(state consumerState) {
+ pc.state.Store(int32(state))
+}
+
+func (pc *partitionConsumer) Close() {
+
+ if pc.getConsumerState() != consumerReady {
+ return
+ }
+
+ // flush all pending ACK requests and terminate the timer goroutine
+ pc.ackGroupingTracker.close()
+
+ // close chunkedMsgCtxMap
+ pc.chunkedMsgCtxMap.Close()
+
+ req := &closeRequest{doneCh: make(chan struct{})}
+ pc.eventsCh <- req
+
+ // wait for request to finish
+ <-req.doneCh
+}
+
+func (pc *partitionConsumer) Seek(msgID MessageID) error {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to seek by closing or closed consumer")
+ return errors.New("failed to seek by closing or closed consumer")
+ }
+
+ if !checkMessageIDType(msgID) {
+ pc.log.Errorf("invalid message id type %T", msgID)
+ return fmt.Errorf("invalid message id type %T", msgID)
+ }
+
+ req := &seekRequest{
+ doneCh: make(chan struct{}),
+ }
+ if cmid, ok := msgID.(*chunkMessageID); ok {
+ req.msgID = cmid.firstChunkID
+ } else {
+ tmid := toTrackingMessageID(msgID)
+ req.msgID = tmid.messageID
+ }
+
+ pc.ackGroupingTracker.flushAndClean()
+ pc.eventsCh <- req
+
+ // wait for the request to complete
+ <-req.doneCh
+ return req.err
+}
+
+func (pc *partitionConsumer) internalSeek(seek *seekRequest) {
+ defer close(seek.doneCh)
+ seek.err = pc.requestSeek(seek.msgID)
+}
+func (pc *partitionConsumer) requestSeek(msgID *messageID) error {
+ if err := pc.requestSeekWithoutClear(msgID); err != nil {
+ return err
+ }
+ pc.clearReceiverQueue()
+ return nil
+}
+
+func (pc *partitionConsumer) requestSeekWithoutClear(msgID *messageID) error {
+ state := pc.getConsumerState()
+ if state == consumerClosing || state == consumerClosed {
+ pc.log.WithField("state", state).Error("failed seek by consumer is closing or has closed")
+ return nil
+ }
+
+ id := &pb.MessageIdData{}
+ err := proto.Unmarshal(msgID.Serialize(), id)
+ if err != nil {
+ pc.log.WithError(err).Errorf("deserialize message id error: %s", err.Error())
+ return err
+ }
+
+ requestID := pc.client.rpcClient.NewRequestID()
+ cmdSeek := &pb.CommandSeek{
+ ConsumerId: proto.Uint64(pc.consumerID),
+ RequestId: proto.Uint64(requestID),
+ MessageId: id,
+ }
+
+ _, err = pc.client.rpcClient.RequestOnCnx(pc._getConn(), requestID, pb.BaseCommand_SEEK, cmdSeek)
+ if err != nil {
+ pc.log.WithError(err).Error("Failed to reset to message id")
+ return err
+ }
+ return nil
+}
+
+func (pc *partitionConsumer) SeekByTime(time time.Time) error {
+ if state := pc.getConsumerState(); state == consumerClosing || state == consumerClosed {
+ pc.log.WithField("state", pc.state).Error("Failed seekByTime by consumer is closing or has closed")
+ return errors.New("failed seekByTime by consumer is closing or has closed")
+ }
+ req := &seekByTimeRequest{
+ doneCh: make(chan struct{}),
+ publishTime: time,
+ }
+ pc.ackGroupingTracker.flushAndClean()
+ pc.eventsCh <- req
+
+ // wait for the request to complete
+ <-req.doneCh
+ return req.err
+}
+
+func (pc *partitionConsumer) internalSeekByTime(seek *seekByTimeRequest) {
+ defer close(seek.doneCh)
+
+ state := pc.getConsumerState()
+ if state == consumerClosing || state == consumerClosed {
+ pc.log.WithField("state", pc.state).Error("Failed seekByTime by consumer is closing or has closed")
+ return
+ }
+
+ requestID := pc.client.rpcClient.NewRequestID()
+ cmdSeek := &pb.CommandSeek{
+ ConsumerId: proto.Uint64(pc.consumerID),
+ RequestId: proto.Uint64(requestID),
+ MessagePublishTime: proto.Uint64(uint64(seek.publishTime.UnixNano() / int64(time.Millisecond))),
+ }
+
+ _, err := pc.client.rpcClient.RequestOnCnx(pc._getConn(), requestID, pb.BaseCommand_SEEK, cmdSeek)
+ if err != nil {
+ pc.log.WithError(err).Error("Failed to reset to message publish time")
+ seek.err = err
+ return
+ }
+ pc.clearReceiverQueue()
+}
+
+func (pc *partitionConsumer) internalAck(req *ackRequest) {
+ defer close(req.doneCh)
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to ack by closing or closed consumer")
+ return
+ }
+ msgID := req.msgID
+
+ messageIDs := make([]*pb.MessageIdData, 1)
+ messageIDs[0] = &pb.MessageIdData{
+ LedgerId: proto.Uint64(uint64(msgID.ledgerID)),
+ EntryId: proto.Uint64(uint64(msgID.entryID)),
+ }
+ if pc.options.enableBatchIndexAck && msgID.tracker != nil {
+ ackSet := msgID.tracker.toAckSet()
+ if ackSet != nil {
+ messageIDs[0].AckSet = ackSet
+ }
+ }
+
+ reqID := pc.client.rpcClient.NewRequestID()
+ cmdAck := &pb.CommandAck{
+ ConsumerId: proto.Uint64(pc.consumerID),
+ MessageId: messageIDs,
+ }
+
+ switch req.ackType {
+ case individualAck:
+ cmdAck.AckType = pb.CommandAck_Individual.Enum()
+ case cumulativeAck:
+ cmdAck.AckType = pb.CommandAck_Cumulative.Enum()
+ }
+
+ if pc.options.ackWithResponse {
+ cmdAck.RequestId = proto.Uint64(reqID)
+ _, err := pc.client.rpcClient.RequestOnCnx(pc._getConn(), reqID, pb.BaseCommand_ACK, cmdAck)
+ if err != nil {
+ pc.log.WithError(err).Error("Ack with response error")
+ req.err = err
+ }
+ return
+ }
+
+ err := pc.client.rpcClient.RequestOnCnxNoWait(pc._getConn(), pb.BaseCommand_ACK, cmdAck)
+ if err != nil {
+ pc.log.Error("Connection was closed when request ack cmd")
+ req.err = err
+ }
+}
+
+func (pc *partitionConsumer) internalAckList(msgIDs []*pb.MessageIdData) {
+ pc.client.rpcClient.RequestOnCnxNoWait(pc._getConn(), pb.BaseCommand_ACK, &pb.CommandAck{
+ AckType: pb.CommandAck_Individual.Enum(),
+ ConsumerId: proto.Uint64(pc.consumerID),
+ MessageId: msgIDs,
+ })
+}
+
+func (pc *partitionConsumer) MessageReceived(response *pb.CommandMessage, headersAndPayload internal.Buffer) error {
+ pbMsgID := response.GetMessageId()
+
+ reader := internal.NewMessageReader(headersAndPayload)
+ brokerMetadata, err := reader.ReadBrokerMetadata()
+ if err != nil {
+ // todo optimize use more appropriate error codes
+ pc.discardCorruptedMessage(pbMsgID, pb.CommandAck_BatchDeSerializeError)
+ return err
+ }
+ msgMeta, err := reader.ReadMessageMetadata()
+ if err != nil {
+ pc.discardCorruptedMessage(pbMsgID, pb.CommandAck_ChecksumMismatch)
+ return err
+ }
+ decryptedPayload, err := pc.decryptor.Decrypt(headersAndPayload.ReadableSlice(), pbMsgID, msgMeta)
+ // error decrypting the payload
+ if err != nil {
+ // default crypto failure action
+ crypToFailureAction := crypto.ConsumerCryptoFailureActionFail
+ if pc.options.decryption != nil {
+ crypToFailureAction = pc.options.decryption.ConsumerCryptoFailureAction
+ }
+
+ switch crypToFailureAction {
+ case crypto.ConsumerCryptoFailureActionFail:
+ pc.log.Errorf("consuming message failed due to decryption err :%v", err)
+ pc.NackID(newTrackingMessageID(int64(pbMsgID.GetLedgerId()), int64(pbMsgID.GetEntryId()), 0, 0, 0, nil))
+ return err
+ case crypto.ConsumerCryptoFailureActionDiscard:
+ pc.discardCorruptedMessage(pbMsgID, pb.CommandAck_DecryptionError)
+ return fmt.Errorf("discarding message on decryption error :%v", err)
+ case crypto.ConsumerCryptoFailureActionConsume:
+ pc.log.Warnf("consuming encrypted message due to error in decryption :%v", err)
+ messages := []*message{
+ {
+ publishTime: timeFromUnixTimestampMillis(msgMeta.GetPublishTime()),
+ eventTime: timeFromUnixTimestampMillis(msgMeta.GetEventTime()),
+ key: msgMeta.GetPartitionKey(),
+ producerName: msgMeta.GetProducerName(),
+ properties: internal.ConvertToStringMap(msgMeta.GetProperties()),
+ topic: pc.topic,
+ msgID: newMessageID(
+ int64(pbMsgID.GetLedgerId()),
+ int64(pbMsgID.GetEntryId()),
+ pbMsgID.GetBatchIndex(),
+ pc.partitionIdx,
+ pbMsgID.GetBatchSize(),
+ ),
+ payLoad: headersAndPayload.ReadableSlice(),
+ schema: pc.options.schema,
+ replicationClusters: msgMeta.GetReplicateTo(),
+ replicatedFrom: msgMeta.GetReplicatedFrom(),
+ redeliveryCount: response.GetRedeliveryCount(),
+ encryptionContext: createEncryptionContext(msgMeta),
+ orderingKey: string(msgMeta.OrderingKey),
+ },
+ }
+
+ if pc.options.autoReceiverQueueSize {
+ pc.incomingMessages.Inc()
+ pc.markScaleIfNeed()
+ }
+
+ pc.queueCh <- messages
+ return nil
+ }
+ }
+
+ isChunkedMsg := false
+ if msgMeta.GetNumChunksFromMsg() > 1 {
+ isChunkedMsg = true
+ }
+
+ processedPayloadBuffer := internal.NewBufferWrapper(decryptedPayload)
+ if isChunkedMsg {
+ processedPayloadBuffer = pc.processMessageChunk(processedPayloadBuffer, msgMeta, pbMsgID)
+ if processedPayloadBuffer == nil {
+ return nil
+ }
+ }
+
+ // decryption is success, decompress the payload
+ uncompressedHeadersAndPayload, err := pc.Decompress(msgMeta, processedPayloadBuffer)
+ if err != nil {
+ pc.discardCorruptedMessage(pbMsgID, pb.CommandAck_DecompressionError)
+ return err
+ }
+
+ // Reset the reader on the uncompressed buffer
+ reader.ResetBuffer(uncompressedHeadersAndPayload)
+
+ numMsgs := 1
+ if msgMeta.NumMessagesInBatch != nil {
+ numMsgs = int(msgMeta.GetNumMessagesInBatch())
+ }
+
+ messages := make([]*message, 0)
+ var ackTracker *ackTracker
+ // are there multiple messages in this batch?
+ if numMsgs > 1 {
+ ackTracker = newAckTracker(uint(numMsgs))
+ }
+
+ var ackSet *bitset.BitSet
+ if response.GetAckSet() != nil {
+ ackSetFromResponse := response.GetAckSet()
+ buf := make([]uint64, len(ackSetFromResponse))
+ for i := 0; i < len(buf); i++ {
+ buf[i] = uint64(ackSetFromResponse[i])
+ }
+ ackSet = bitset.From(buf)
+ }
+
+ pc.metrics.MessagesReceived.Add(float64(numMsgs))
+ pc.metrics.PrefetchedMessages.Add(float64(numMsgs))
+
+ var bytesReceived int
+ for i := 0; i < numMsgs; i++ {
+ smm, payload, err := reader.ReadMessage()
+ if err != nil || payload == nil {
+ pc.discardCorruptedMessage(pbMsgID, pb.CommandAck_BatchDeSerializeError)
+ return err
+ }
+ if ackSet != nil && !ackSet.Test(uint(i)) {
+ pc.log.Debugf("Ignoring message from %vth message, which has been acknowledged", i)
+ continue
+ }
+
+ pc.metrics.BytesReceived.Add(float64(len(payload)))
+ pc.metrics.PrefetchedBytes.Add(float64(len(payload)))
+
+ trackingMsgID := newTrackingMessageID(
+ int64(pbMsgID.GetLedgerId()),
+ int64(pbMsgID.GetEntryId()),
+ int32(i),
+ pc.partitionIdx,
+ int32(numMsgs),
+ ackTracker)
+ // set the consumer so we know how to ack the message id
+ trackingMsgID.consumer = pc
+
+ if pc.messageShouldBeDiscarded(trackingMsgID) {
+ pc.AckID(trackingMsgID)
+ continue
+ }
+
+ var msgID MessageID
+ if isChunkedMsg {
+ ctx := pc.chunkedMsgCtxMap.get(msgMeta.GetUuid())
+ if ctx == nil {
+ // chunkedMsgCtxMap has closed because of consumer closed
+ pc.log.Warnf("get chunkedMsgCtx for chunk with uuid %s failed because consumer has closed",
+ msgMeta.Uuid)
+ return nil
+ }
+ cmid := newChunkMessageID(ctx.firstChunkID(), ctx.lastChunkID())
+ // set the consumer so we know how to ack the message id
+ cmid.consumer = pc
+ // clean chunkedMsgCtxMap
+ pc.chunkedMsgCtxMap.remove(msgMeta.GetUuid())
+ pc.unAckChunksTracker.add(cmid, ctx.chunkedMsgIDs)
+ msgID = cmid
+ } else {
+ msgID = trackingMsgID
+ }
+
+ if pc.ackGroupingTracker.isDuplicate(msgID) {
+ continue
+ }
+
+ var messageIndex *uint64
+ var brokerPublishTime *time.Time
+ if brokerMetadata != nil {
+ if brokerMetadata.Index != nil {
+ aux := brokerMetadata.GetIndex() - uint64(numMsgs) + uint64(i) + 1
+ messageIndex = &aux
+ }
+ if brokerMetadata.BrokerTimestamp != nil {
+ aux := timeFromUnixTimestampMillis(*brokerMetadata.BrokerTimestamp)
+ brokerPublishTime = &aux
+ }
+ }
+
+ var msg *message
+ if smm != nil {
+ msg = &message{
+ publishTime: timeFromUnixTimestampMillis(msgMeta.GetPublishTime()),
+ eventTime: timeFromUnixTimestampMillis(smm.GetEventTime()),
+ key: smm.GetPartitionKey(),
+ producerName: msgMeta.GetProducerName(),
+ properties: internal.ConvertToStringMap(smm.GetProperties()),
+ topic: pc.topic,
+ msgID: msgID,
+ payLoad: payload,
+ schema: pc.options.schema,
+ replicationClusters: msgMeta.GetReplicateTo(),
+ replicatedFrom: msgMeta.GetReplicatedFrom(),
+ redeliveryCount: response.GetRedeliveryCount(),
+ schemaVersion: msgMeta.GetSchemaVersion(),
+ schemaInfoCache: pc.schemaInfoCache,
+ orderingKey: string(smm.OrderingKey),
+ index: messageIndex,
+ brokerPublishTime: brokerPublishTime,
+ }
+ } else {
+ msg = &message{
+ publishTime: timeFromUnixTimestampMillis(msgMeta.GetPublishTime()),
+ eventTime: timeFromUnixTimestampMillis(msgMeta.GetEventTime()),
+ key: msgMeta.GetPartitionKey(),
+ producerName: msgMeta.GetProducerName(),
+ properties: internal.ConvertToStringMap(msgMeta.GetProperties()),
+ topic: pc.topic,
+ msgID: msgID,
+ payLoad: payload,
+ schema: pc.options.schema,
+ replicationClusters: msgMeta.GetReplicateTo(),
+ replicatedFrom: msgMeta.GetReplicatedFrom(),
+ redeliveryCount: response.GetRedeliveryCount(),
+ schemaVersion: msgMeta.GetSchemaVersion(),
+ schemaInfoCache: pc.schemaInfoCache,
+ index: messageIndex,
+ brokerPublishTime: brokerPublishTime,
+ }
+ }
+
+ pc.options.interceptors.BeforeConsume(ConsumerMessage{
+ Consumer: pc.parentConsumer,
+ Message: msg,
+ })
+
+ messages = append(messages, msg)
+ bytesReceived += msg.size()
+ }
+
+ if pc.options.autoReceiverQueueSize {
+ pc.client.memLimit.ForceReserveMemory(int64(bytesReceived))
+ pc.incomingMessages.Add(int32(len(messages)))
+ pc.markScaleIfNeed()
+ }
+
+ // send messages to the dispatcher
+ pc.queueCh <- messages
+ return nil
+}
+
+func (pc *partitionConsumer) processMessageChunk(compressedPayload internal.Buffer,
+ msgMeta *pb.MessageMetadata,
+ pbMsgID *pb.MessageIdData) internal.Buffer {
+ uuid := msgMeta.GetUuid()
+ numChunks := msgMeta.GetNumChunksFromMsg()
+ totalChunksSize := int(msgMeta.GetTotalChunkMsgSize())
+ chunkID := msgMeta.GetChunkId()
+ msgID := &messageID{
+ ledgerID: int64(pbMsgID.GetLedgerId()),
+ entryID: int64(pbMsgID.GetEntryId()),
+ batchIdx: -1,
+ partitionIdx: pc.partitionIdx,
+ }
+
+ if msgMeta.GetChunkId() == 0 {
+ pc.chunkedMsgCtxMap.addIfAbsent(uuid,
+ numChunks,
+ totalChunksSize,
+ )
+ }
+
+ ctx := pc.chunkedMsgCtxMap.get(uuid)
+
+ if ctx == nil || ctx.chunkedMsgBuffer == nil || chunkID != ctx.lastChunkedMsgID+1 {
+ lastChunkedMsgID := -1
+ totalChunks := -1
+ if ctx != nil {
+ lastChunkedMsgID = int(ctx.lastChunkedMsgID)
+ totalChunks = int(ctx.totalChunks)
+ ctx.chunkedMsgBuffer.Clear()
+ }
+ pc.log.Warnf(fmt.Sprintf(
+ "Received unexpected chunk messageId %s, last-chunk-id %d, chunkId = %d, total-chunks %d",
+ msgID.String(), lastChunkedMsgID, chunkID, totalChunks))
+ pc.chunkedMsgCtxMap.remove(uuid)
+ pc.availablePermits.inc()
+ return nil
+ }
+
+ ctx.append(chunkID, msgID, compressedPayload)
+
+ if msgMeta.GetChunkId() != msgMeta.GetNumChunksFromMsg()-1 {
+ pc.availablePermits.inc()
+ return nil
+ }
+
+ return ctx.chunkedMsgBuffer
+}
+
+func (pc *partitionConsumer) messageShouldBeDiscarded(msgID *trackingMessageID) bool {
+ if pc.startMessageID.get() == nil {
+ return false
+ }
+ // if we start at latest message, we should never discard
+ if pc.options.startMessageID != nil && pc.options.startMessageID.equal(latestMessageID) {
+ return false
+ }
+
+ if pc.options.startMessageIDInclusive {
+ return pc.startMessageID.get().greater(msgID.messageID)
+ }
+
+ // Non inclusive
+ return pc.startMessageID.get().greaterEqual(msgID.messageID)
+}
+
+// create EncryptionContext from message metadata
+// this will be used to decrypt the message payload outside of this client
+// it is the responsibility of end user to decrypt the payload
+// It will be used only when crypto failure action is set to consume i.e crypto.ConsumerCryptoFailureActionConsume
+func createEncryptionContext(msgMeta *pb.MessageMetadata) *EncryptionContext {
+ encCtx := EncryptionContext{
+ Algorithm: msgMeta.GetEncryptionAlgo(),
+ Param: msgMeta.GetEncryptionParam(),
+ UncompressedSize: int(msgMeta.GetUncompressedSize()),
+ BatchSize: int(msgMeta.GetNumMessagesInBatch()),
+ }
+
+ if msgMeta.Compression != nil {
+ encCtx.CompressionType = CompressionType(*msgMeta.Compression)
+ }
+
+ keyMap := map[string]EncryptionKey{}
+ for _, k := range msgMeta.GetEncryptionKeys() {
+ metaMap := map[string]string{}
+ for _, m := range k.GetMetadata() {
+ metaMap[*m.Key] = *m.Value
+ }
+
+ keyMap[*k.Key] = EncryptionKey{
+ KeyValue: k.GetValue(),
+ Metadata: metaMap,
+ }
+ }
+
+ encCtx.Keys = keyMap
+ return &encCtx
+}
+
+func (pc *partitionConsumer) ConnectionClosed() {
+ // Trigger reconnection in the consumer goroutine
+ pc.log.Debug("connection closed and send to connectClosedCh")
+ pc.connectClosedCh <- connectionClosed{}
+}
+
+// Flow command gives additional permits to send messages to the consumer.
+// A typical consumer implementation will use a queue to accumulate these messages
+// before the application is ready to consume them. After the consumer is ready,
+// the client needs to give permission to the broker to push messages.
+func (pc *partitionConsumer) internalFlow(permits uint32) error {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to redeliver closing or closed consumer")
+ return errors.New("consumer closing or closed")
+ }
+ if permits == 0 {
+ return fmt.Errorf("invalid number of permits requested: %d", permits)
+ }
+
+ cmdFlow := &pb.CommandFlow{
+ ConsumerId: proto.Uint64(pc.consumerID),
+ MessagePermits: proto.Uint32(permits),
+ }
+ err := pc.client.rpcClient.RequestOnCnxNoWait(pc._getConn(), pb.BaseCommand_FLOW, cmdFlow)
+ if err != nil {
+ pc.log.Error("Connection was closed when request flow cmd")
+ return err
+ }
+
+ return nil
+}
+
+// dispatcher manages the internal message queue channel
+// and manages the flow control
+func (pc *partitionConsumer) dispatcher() {
+ defer func() {
+ pc.log.Debug("exiting dispatch loop")
+ }()
+ var messages []*message
+ for {
+ var queueCh chan []*message
+ var messageCh chan ConsumerMessage
+ var nextMessage ConsumerMessage
+ var nextMessageSize int
+
+ // are there more messages to send?
+ if len(messages) > 0 {
+ nextMessage = ConsumerMessage{
+ Consumer: pc.parentConsumer,
+ Message: messages[0],
+ }
+ nextMessageSize = messages[0].size()
+
+ if pc.dlq.shouldSendToDlq(&nextMessage) {
+ // pass the message to the DLQ router
+ pc.metrics.DlqCounter.Inc()
+ messageCh = pc.dlq.Chan()
+ } else {
+ // pass the message to application channel
+ messageCh = pc.messageCh
+ }
+
+ pc.metrics.PrefetchedMessages.Dec()
+ pc.metrics.PrefetchedBytes.Sub(float64(len(messages[0].payLoad)))
+ } else {
+ queueCh = pc.queueCh
+ }
+
+ select {
+ case <-pc.closeCh:
+ return
+
+ case _, ok := <-pc.connectedCh:
+ if !ok {
+ return
+ }
+ pc.log.Debug("dispatcher received connection event")
+
+ messages = nil
+
+ // reset available permits
+ pc.availablePermits.reset()
+
+ var initialPermits uint32
+ if pc.options.autoReceiverQueueSize {
+ initialPermits = uint32(pc.currentQueueSize.Load())
+ } else {
+ initialPermits = uint32(pc.maxQueueSize)
+ }
+
+ pc.log.Debugf("dispatcher requesting initial permits=%d", initialPermits)
+ // send initial permits
+ if err := pc.internalFlow(initialPermits); err != nil {
+ pc.log.WithError(err).Error("unable to send initial permits to broker")
+ }
+
+ case msgs, ok := <-queueCh:
+ if !ok {
+ return
+ }
+ // we only read messages here after the consumer has processed all messages
+ // in the previous batch
+ messages = msgs
+
+ // if the messageCh is nil or the messageCh is full this will not be selected
+ case messageCh <- nextMessage:
+ // allow this message to be garbage collected
+ messages[0] = nil
+ messages = messages[1:]
+
+ pc.availablePermits.inc()
+
+ if pc.options.autoReceiverQueueSize {
+ pc.incomingMessages.Dec()
+ pc.client.memLimit.ReleaseMemory(int64(nextMessageSize))
+ pc.expectMoreIncomingMessages()
+ }
+
+ case clearQueueCb := <-pc.clearQueueCh:
+ // drain the message queue on any new connection by sending a
+ // special nil message to the channel so we know when to stop dropping messages
+ var nextMessageInQueue *trackingMessageID
+ go func() {
+ pc.queueCh <- nil
+ }()
+
+ for m := range pc.queueCh {
+ // the queue has been drained
+ if m == nil {
+ break
+ } else if nextMessageInQueue == nil {
+ nextMessageInQueue = toTrackingMessageID(m[0].msgID)
+ }
+ if pc.options.autoReceiverQueueSize {
+ pc.incomingMessages.Sub(int32(len(m)))
+ }
+ }
+
+ messages = nil
+
+ clearQueueCb(nextMessageInQueue)
+ }
+ }
+}
+
+const (
+ individualAck = iota
+ cumulativeAck
+)
+
+type ackRequest struct {
+ doneCh chan struct{}
+ msgID trackingMessageID
+ ackType int
+ err error
+}
+
+type unsubscribeRequest struct {
+ doneCh chan struct{}
+ err error
+}
+
+type closeRequest struct {
+ doneCh chan struct{}
+}
+
+type redeliveryRequest struct {
+ msgIds []messageID
+}
+
+type getLastMsgIDRequest struct {
+ doneCh chan struct{}
+ msgID *trackingMessageID
+ err error
+}
+
+type seekRequest struct {
+ doneCh chan struct{}
+ msgID *messageID
+ err error
+}
+
+type seekByTimeRequest struct {
+ doneCh chan struct{}
+ publishTime time.Time
+ err error
+}
+
+func (pc *partitionConsumer) runEventsLoop() {
+ defer func() {
+ pc.log.Debug("exiting events loop")
+ }()
+ pc.log.Debug("get into runEventsLoop")
+
+ go func() {
+ for {
+ select {
+ case <-pc.closeCh:
+ pc.log.Info("close consumer, exit reconnect")
+ return
+ case <-pc.connectClosedCh:
+ pc.log.Debug("runEventsLoop will reconnect")
+ pc.reconnectToBroker()
+ }
+ }
+ }()
+
+ for {
+ for i := range pc.eventsCh {
+ switch v := i.(type) {
+ case *ackRequest:
+ pc.internalAck(v)
+ case []*pb.MessageIdData:
+ pc.internalAckList(v)
+ case *redeliveryRequest:
+ pc.internalRedeliver(v)
+ case *unsubscribeRequest:
+ pc.internalUnsubscribe(v)
+ case *getLastMsgIDRequest:
+ pc.internalGetLastMessageID(v)
+ case *seekRequest:
+ pc.internalSeek(v)
+ case *seekByTimeRequest:
+ pc.internalSeekByTime(v)
+ case *closeRequest:
+ pc.internalClose(v)
+ return
+ }
+ }
+ }
+}
+
+func (pc *partitionConsumer) internalClose(req *closeRequest) {
+ defer close(req.doneCh)
+ state := pc.getConsumerState()
+ if state != consumerReady {
+ // this might be redundant but to ensure nack tracker is closed
+ if pc.nackTracker != nil {
+ pc.nackTracker.Close()
+ }
+ return
+ }
+
+ if state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Consumer is closing or has closed")
+ if pc.nackTracker != nil {
+ pc.nackTracker.Close()
+ }
+ return
+ }
+
+ pc.setConsumerState(consumerClosing)
+ pc.log.Infof("Closing consumer=%d", pc.consumerID)
+
+ requestID := pc.client.rpcClient.NewRequestID()
+ cmdClose := &pb.CommandCloseConsumer{
+ ConsumerId: proto.Uint64(pc.consumerID),
+ RequestId: proto.Uint64(requestID),
+ }
+ _, err := pc.client.rpcClient.RequestOnCnx(pc._getConn(), requestID, pb.BaseCommand_CLOSE_CONSUMER, cmdClose)
+ if err != nil {
+ pc.log.WithError(err).Warn("Failed to close consumer")
+ } else {
+ pc.log.Info("Closed consumer")
+ }
+
+ pc.compressionProviders.Range(func(_, v interface{}) bool {
+ if provider, ok := v.(compression.Provider); ok {
+ provider.Close()
+ } else {
+ err := fmt.Errorf("unexpected compression provider type: %T", v)
+ pc.log.WithError(err).Warn("Failed to close compression provider")
+ }
+ return true
+ })
+
+ pc.setConsumerState(consumerClosed)
+ pc._getConn().DeleteConsumeHandler(pc.consumerID)
+ if pc.nackTracker != nil {
+ pc.nackTracker.Close()
+ }
+ close(pc.closeCh)
+}
+
+func (pc *partitionConsumer) reconnectToBroker() {
+ var maxRetry int
+
+ if pc.options.maxReconnectToBroker == nil {
+ maxRetry = -1
+ } else {
+ maxRetry = int(*pc.options.maxReconnectToBroker)
+ }
+
+ for maxRetry != 0 {
+ if pc.getConsumerState() != consumerReady {
+ // Consumer is already closing
+ pc.log.Info("consumer state not ready, exit reconnect")
+ return
+ }
+
+ var (
+ delayReconnectTime time.Duration
+ defaultBackoff = internal.DefaultBackoff{}
+ )
+
+ if pc.options.backoffPolicy == nil {
+ delayReconnectTime = defaultBackoff.Next()
+ } else {
+ delayReconnectTime = pc.options.backoffPolicy.Next()
+ }
+
+ pc.log.Info("Reconnecting to broker in ", delayReconnectTime)
+ time.Sleep(delayReconnectTime)
+
+ err := pc.grabConn()
+ if err == nil {
+ // Successfully reconnected
+ pc.log.Info("Reconnected consumer to broker")
+ return
+ }
+ pc.log.WithError(err).Error("Failed to create consumer at reconnect")
+ errMsg := err.Error()
+ if strings.Contains(errMsg, errTopicNotFount) {
+ // when topic is deleted, we should give up reconnection.
+ pc.log.Warn("Topic Not Found.")
+ break
+ }
+
+ if maxRetry > 0 {
+ maxRetry--
+ }
+ pc.metrics.ConsumersReconnectFailure.Inc()
+ if maxRetry == 0 || defaultBackoff.IsMaxBackoffReached() {
+ pc.metrics.ConsumersReconnectMaxRetry.Inc()
+ }
+ }
+}
+
+func (pc *partitionConsumer) grabConn() error {
+ lr, err := pc.client.lookupService.Lookup(pc.topic)
+ if err != nil {
+ pc.log.WithError(err).Warn("Failed to lookup topic")
+ return err
+ }
+ pc.log.Debugf("Lookup result: %+v", lr)
+
+ subType := toProtoSubType(pc.options.subscriptionType)
+ initialPosition := toProtoInitialPosition(pc.options.subscriptionInitPos)
+ keySharedMeta := toProtoKeySharedMeta(pc.options.keySharedPolicy)
+ requestID := pc.client.rpcClient.NewRequestID()
+
+ var pbSchema *pb.Schema
+
+ if pc.options.schema != nil && pc.options.schema.GetSchemaInfo() != nil {
+ tmpSchemaType := pb.Schema_Type(int32(pc.options.schema.GetSchemaInfo().Type))
+ pbSchema = &pb.Schema{
+ Name: proto.String(pc.options.schema.GetSchemaInfo().Name),
+ Type: &tmpSchemaType,
+ SchemaData: []byte(pc.options.schema.GetSchemaInfo().Schema),
+ Properties: internal.ConvertFromStringMap(pc.options.schema.GetSchemaInfo().Properties),
+ }
+ pc.log.Debugf("The partition consumer schema name is: %s", pbSchema.Name)
+ } else {
+ pc.log.Debug("The partition consumer schema is nil")
+ }
+
+ cmdSubscribe := &pb.CommandSubscribe{
+ Topic: proto.String(pc.topic),
+ Subscription: proto.String(pc.options.subscription),
+ SubType: subType.Enum(),
+ ConsumerId: proto.Uint64(pc.consumerID),
+ RequestId: proto.Uint64(requestID),
+ ConsumerName: proto.String(pc.name),
+ PriorityLevel: nil,
+ Durable: proto.Bool(pc.options.subscriptionMode == durable),
+ Metadata: internal.ConvertFromStringMap(pc.options.metadata),
+ SubscriptionProperties: internal.ConvertFromStringMap(pc.options.subProperties),
+ ReadCompacted: proto.Bool(pc.options.readCompacted),
+ Schema: pbSchema,
+ InitialPosition: initialPosition.Enum(),
+ ReplicateSubscriptionState: proto.Bool(pc.options.replicateSubscriptionState),
+ KeySharedMeta: keySharedMeta,
+ }
+
+ pc.startMessageID.set(pc.clearReceiverQueue())
+ if pc.options.subscriptionMode != durable {
+ // For regular subscriptions the broker will determine the restarting point
+ cmdSubscribe.StartMessageId = convertToMessageIDData(pc.startMessageID.get())
+ }
+
+ if len(pc.options.metadata) > 0 {
+ cmdSubscribe.Metadata = toKeyValues(pc.options.metadata)
+ }
+
+ if len(pc.options.subProperties) > 0 {
+ cmdSubscribe.SubscriptionProperties = toKeyValues(pc.options.subProperties)
+ }
+
+ // force topic creation is enabled by default so
+ // we only need to set the flag when disabling it
+ if pc.options.disableForceTopicCreation {
+ cmdSubscribe.ForceTopicCreation = proto.Bool(false)
+ }
+
+ res, err := pc.client.rpcClient.Request(lr.LogicalAddr, lr.PhysicalAddr, requestID,
+ pb.BaseCommand_SUBSCRIBE, cmdSubscribe)
+
+ if err != nil {
+ pc.log.WithError(err).Error("Failed to create consumer")
+ return err
+ }
+
+ if res.Response.ConsumerStatsResponse != nil {
+ pc.name = res.Response.ConsumerStatsResponse.GetConsumerName()
+ }
+
+ pc._setConn(res.Cnx)
+ pc.log.Info("Connected consumer")
+ err = pc._getConn().AddConsumeHandler(pc.consumerID, pc)
+ if err != nil {
+ pc.log.WithError(err).Error("Failed to add consumer handler")
+ return err
+ }
+
+ msgType := res.Response.GetType()
+
+ switch msgType {
+ case pb.BaseCommand_SUCCESS:
+ // notify the dispatcher we have connection
+ go func() {
+ pc.connectedCh <- struct{}{}
+ }()
+ return nil
+ case pb.BaseCommand_ERROR:
+ errMsg := res.Response.GetError()
+ return fmt.Errorf("%s: %s", errMsg.GetError().String(), errMsg.GetMessage())
+ default:
+ return newUnexpectedErrMsg(msgType, requestID)
+ }
+}
+
+func (pc *partitionConsumer) clearQueueAndGetNextMessage() *trackingMessageID {
+ if pc.getConsumerState() != consumerReady {
+ return nil
+ }
+ wg := &sync.WaitGroup{}
+ wg.Add(1)
+ var msgID *trackingMessageID
+
+ pc.clearQueueCh <- func(id *trackingMessageID) {
+ msgID = id
+ wg.Done()
+ }
+
+ wg.Wait()
+ return msgID
+}
+
+/**
+ * Clear the internal receiver queue and returns the message id of what was the 1st message in the queue that was
+ * not seen by the application
+ */
+func (pc *partitionConsumer) clearReceiverQueue() *trackingMessageID {
+ nextMessageInQueue := pc.clearQueueAndGetNextMessage()
+
+ if pc.startMessageID.get() == nil {
+ return pc.startMessageID.get()
+ }
+
+ if nextMessageInQueue != nil {
+ return getPreviousMessage(nextMessageInQueue)
+ } else if pc.lastDequeuedMsg != nil {
+ // If the queue was empty we need to restart from the message just after the last one that has been dequeued
+ // in the past
+ return pc.lastDequeuedMsg
+ } else {
+ // No message was received or dequeued by this consumer. Next message would still be the startMessageId
+ return pc.startMessageID.get()
+ }
+}
+
+func getPreviousMessage(mid *trackingMessageID) *trackingMessageID {
+ if mid.batchIdx >= 0 {
+ return &trackingMessageID{
+ messageID: &messageID{
+ ledgerID: mid.ledgerID,
+ entryID: mid.entryID,
+ batchIdx: mid.batchIdx - 1,
+ partitionIdx: mid.partitionIdx,
+ },
+ tracker: mid.tracker,
+ consumer: mid.consumer,
+ receivedTime: mid.receivedTime,
+ }
+ }
+
+ // Get on previous message in previous entry
+ return &trackingMessageID{
+ messageID: &messageID{
+ ledgerID: mid.ledgerID,
+ entryID: mid.entryID - 1,
+ batchIdx: mid.batchIdx,
+ partitionIdx: mid.partitionIdx,
+ },
+ tracker: mid.tracker,
+ consumer: mid.consumer,
+ receivedTime: mid.receivedTime,
+ }
+}
+
+func (pc *partitionConsumer) expectMoreIncomingMessages() {
+ if !pc.options.autoReceiverQueueSize {
+ return
+ }
+ if pc.scaleReceiverQueueHint.CAS(true, false) {
+ oldSize := pc.currentQueueSize.Load()
+ maxSize := int32(pc.options.receiverQueueSize)
+ newSize := int32(math.Min(float64(maxSize), float64(oldSize*2)))
+ usagePercent := pc.client.memLimit.CurrentUsagePercent()
+ if usagePercent < receiverQueueExpansionMemThreshold && newSize > oldSize {
+ pc.currentQueueSize.CAS(oldSize, newSize)
+ pc.availablePermits.add(newSize - oldSize)
+ pc.log.Debugf("update currentQueueSize from %d -> %d", oldSize, newSize)
+ }
+ }
+}
+
+func (pc *partitionConsumer) markScaleIfNeed() {
+ // availablePermits + incomingMessages (messages in queueCh) is the number of prefetched messages
+ // The result of auto-scale we expected is currentQueueSize is slightly bigger than prefetched messages
+ prev := pc.scaleReceiverQueueHint.Swap(pc.availablePermits.get()+pc.incomingMessages.Load() >=
+ pc.currentQueueSize.Load())
+ if prev != pc.scaleReceiverQueueHint.Load() {
+ pc.log.Debugf("update scaleReceiverQueueHint from %t -> %t", prev, pc.scaleReceiverQueueHint.Load())
+ }
+}
+
+func (pc *partitionConsumer) shrinkReceiverQueueSize() {
+ if !pc.options.autoReceiverQueueSize {
+ return
+ }
+
+ oldSize := pc.currentQueueSize.Load()
+ minSize := int32(math.Min(float64(initialReceiverQueueSize), float64(pc.options.receiverQueueSize)))
+ newSize := int32(math.Max(float64(minSize), float64(oldSize/2)))
+ if newSize < oldSize {
+ pc.currentQueueSize.CAS(oldSize, newSize)
+ pc.availablePermits.add(newSize - oldSize)
+ pc.log.Debugf("update currentQueueSize from %d -> %d", oldSize, newSize)
+ }
+}
+
+func (pc *partitionConsumer) Decompress(msgMeta *pb.MessageMetadata, payload internal.Buffer) (internal.Buffer, error) {
+ providerEntry, ok := pc.compressionProviders.Load(msgMeta.GetCompression())
+ if !ok {
+ newProvider, err := pc.initializeCompressionProvider(msgMeta.GetCompression())
+ if err != nil {
+ pc.log.WithError(err).Error("Failed to decompress message.")
+ return nil, err
+ }
+
+ var loaded bool
+ providerEntry, loaded = pc.compressionProviders.LoadOrStore(msgMeta.GetCompression(), newProvider)
+ if loaded {
+ // another thread already loaded this provider, so close the one we just initialized
+ newProvider.Close()
+ }
+ }
+ provider, ok := providerEntry.(compression.Provider)
+ if !ok {
+ err := fmt.Errorf("unexpected compression provider type: %T", providerEntry)
+ pc.log.WithError(err).Error("Failed to decompress message.")
+ return nil, err
+ }
+
+ uncompressed, err := provider.Decompress(nil, payload.ReadableSlice(), int(msgMeta.GetUncompressedSize()))
+ if err != nil {
+ return nil, err
+ }
+
+ return internal.NewBufferWrapper(uncompressed), nil
+}
+
+func (pc *partitionConsumer) initializeCompressionProvider(
+ compressionType pb.CompressionType) (compression.Provider, error) {
+ switch compressionType {
+ case pb.CompressionType_NONE:
+ return compression.NewNoopProvider(), nil
+ case pb.CompressionType_ZLIB:
+ return compression.NewZLibProvider(), nil
+ case pb.CompressionType_LZ4:
+ return compression.NewLz4Provider(), nil
+ case pb.CompressionType_ZSTD:
+ return compression.NewZStdProvider(compression.Default), nil
+ }
+
+ return nil, fmt.Errorf("unsupported compression type: %v", compressionType)
+}
+
+func (pc *partitionConsumer) discardCorruptedMessage(msgID *pb.MessageIdData,
+ validationError pb.CommandAck_ValidationError) {
+ if state := pc.getConsumerState(); state == consumerClosed || state == consumerClosing {
+ pc.log.WithField("state", state).Error("Failed to discardCorruptedMessage " +
+ "by closing or closed consumer")
+ return
+ }
+ pc.log.WithFields(log.Fields{
+ "msgID": msgID,
+ "validationError": validationError,
+ }).Error("Discarding corrupted message")
+
+ err := pc.client.rpcClient.RequestOnCnxNoWait(pc._getConn(),
+ pb.BaseCommand_ACK, &pb.CommandAck{
+ ConsumerId: proto.Uint64(pc.consumerID),
+ MessageId: []*pb.MessageIdData{msgID},
+ AckType: pb.CommandAck_Individual.Enum(),
+ ValidationError: validationError.Enum(),
+ })
+ if err != nil {
+ pc.log.Error("Connection was closed when request ack cmd")
+ }
+ pc.availablePermits.inc()
+}
+
+// _setConn sets the internal connection field of this partition consumer atomically.
+// Note: should only be called by this partition consumer when a new connection is available.
+func (pc *partitionConsumer) _setConn(conn internal.Connection) {
+ pc.conn.Store(conn)
+}
+
+// _getConn returns internal connection field of this partition consumer atomically.
+// Note: should only be called by this partition consumer before attempting to use the connection
+func (pc *partitionConsumer) _getConn() internal.Connection {
+ // Invariant: The conn must be non-nill for the lifetime of the partitionConsumer.
+ // For this reason we leave this cast unchecked and panic() if the
+ // invariant is broken
+ return pc.conn.Load().(internal.Connection)
+}
+
+func convertToMessageIDData(msgID *trackingMessageID) *pb.MessageIdData {
+ if msgID == nil {
+ return nil
+ }
+
+ return &pb.MessageIdData{
+ LedgerId: proto.Uint64(uint64(msgID.ledgerID)),
+ EntryId: proto.Uint64(uint64(msgID.entryID)),
+ }
+}
+
+func convertToMessageID(id *pb.MessageIdData) *trackingMessageID {
+ if id == nil {
+ return nil
+ }
+
+ msgID := &trackingMessageID{
+ messageID: &messageID{
+ ledgerID: int64(*id.LedgerId),
+ entryID: int64(*id.EntryId),
+ },
+ }
+ if id.BatchIndex != nil {
+ msgID.batchIdx = *id.BatchIndex
+ }
+
+ return msgID
+}
+
+type chunkedMsgCtx struct {
+ totalChunks int32
+ chunkedMsgBuffer internal.Buffer
+ lastChunkedMsgID int32
+ chunkedMsgIDs []*messageID
+ receivedTime int64
+
+ mu sync.Mutex
+}
+
+func newChunkedMsgCtx(numChunksFromMsg int32, totalChunkMsgSize int) *chunkedMsgCtx {
+ return &chunkedMsgCtx{
+ totalChunks: numChunksFromMsg,
+ chunkedMsgBuffer: internal.NewBuffer(totalChunkMsgSize),
+ lastChunkedMsgID: -1,
+ chunkedMsgIDs: make([]*messageID, numChunksFromMsg),
+ receivedTime: time.Now().Unix(),
+ }
+}
+
+func (c *chunkedMsgCtx) append(chunkID int32, msgID *messageID, partPayload internal.Buffer) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ c.chunkedMsgIDs[chunkID] = msgID
+ c.chunkedMsgBuffer.Write(partPayload.ReadableSlice())
+ c.lastChunkedMsgID = chunkID
+}
+
+func (c *chunkedMsgCtx) firstChunkID() *messageID {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if len(c.chunkedMsgIDs) == 0 {
+ return nil
+ }
+ return c.chunkedMsgIDs[0]
+}
+
+func (c *chunkedMsgCtx) lastChunkID() *messageID {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if len(c.chunkedMsgIDs) == 0 {
+ return nil
+ }
+ return c.chunkedMsgIDs[len(c.chunkedMsgIDs)-1]
+}
+
+func (c *chunkedMsgCtx) discard(pc *partitionConsumer) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ for _, mid := range c.chunkedMsgIDs {
+ if mid == nil {
+ continue
+ }
+ pc.log.Info("Removing chunk message-id", mid.String())
+ tmid := toTrackingMessageID(mid)
+ pc.AckID(tmid)
+ }
+}
+
+type chunkedMsgCtxMap struct {
+ chunkedMsgCtxs map[string]*chunkedMsgCtx
+ pendingQueue *list.List
+ maxPending int
+ pc *partitionConsumer
+ mu sync.Mutex
+ closed bool
+}
+
+func newChunkedMsgCtxMap(maxPending int, pc *partitionConsumer) *chunkedMsgCtxMap {
+ return &chunkedMsgCtxMap{
+ chunkedMsgCtxs: make(map[string]*chunkedMsgCtx, maxPending),
+ pendingQueue: list.New(),
+ maxPending: maxPending,
+ pc: pc,
+ mu: sync.Mutex{},
+ }
+}
+
+func (c *chunkedMsgCtxMap) addIfAbsent(uuid string, totalChunks int32, totalChunkMsgSize int) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.closed {
+ return
+ }
+ if _, ok := c.chunkedMsgCtxs[uuid]; !ok {
+ c.chunkedMsgCtxs[uuid] = newChunkedMsgCtx(totalChunks, totalChunkMsgSize)
+ c.pendingQueue.PushBack(uuid)
+ go c.discardChunkIfExpire(uuid, true, c.pc.options.expireTimeOfIncompleteChunk)
+ }
+ if c.maxPending > 0 && c.pendingQueue.Len() > c.maxPending {
+ go c.discardOldestChunkMessage(c.pc.options.autoAckIncompleteChunk)
+ }
+}
+
+func (c *chunkedMsgCtxMap) get(uuid string) *chunkedMsgCtx {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.closed {
+ return nil
+ }
+ return c.chunkedMsgCtxs[uuid]
+}
+
+func (c *chunkedMsgCtxMap) remove(uuid string) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.closed {
+ return
+ }
+ delete(c.chunkedMsgCtxs, uuid)
+ e := c.pendingQueue.Front()
+ for ; e != nil; e = e.Next() {
+ if e.Value.(string) == uuid {
+ c.pendingQueue.Remove(e)
+ break
+ }
+ }
+}
+
+func (c *chunkedMsgCtxMap) discardOldestChunkMessage(autoAck bool) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.closed || (c.maxPending > 0 && c.pendingQueue.Len() <= c.maxPending) {
+ return
+ }
+ oldest := c.pendingQueue.Front().Value.(string)
+ ctx, ok := c.chunkedMsgCtxs[oldest]
+ if !ok {
+ return
+ }
+ if autoAck {
+ ctx.discard(c.pc)
+ }
+ delete(c.chunkedMsgCtxs, oldest)
+ c.pc.log.Infof("Chunked message [%s] has been removed from chunkedMsgCtxMap", oldest)
+}
+
+func (c *chunkedMsgCtxMap) discardChunkMessage(uuid string, autoAck bool) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.closed {
+ return
+ }
+ ctx, ok := c.chunkedMsgCtxs[uuid]
+ if !ok {
+ return
+ }
+ if autoAck {
+ ctx.discard(c.pc)
+ }
+ delete(c.chunkedMsgCtxs, uuid)
+ e := c.pendingQueue.Front()
+ for ; e != nil; e = e.Next() {
+ if e.Value.(string) == uuid {
+ c.pendingQueue.Remove(e)
+ break
+ }
+ }
+ c.pc.log.Infof("Chunked message [%s] has been removed from chunkedMsgCtxMap", uuid)
+}
+
+func (c *chunkedMsgCtxMap) discardChunkIfExpire(uuid string, autoAck bool, expire time.Duration) {
+ timer := time.NewTimer(expire)
+ <-timer.C
+ c.discardChunkMessage(uuid, autoAck)
+}
+
+func (c *chunkedMsgCtxMap) Close() {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ c.closed = true
+}
+
+type unAckChunksTracker struct {
+ // TODO: use hash code of chunkMessageID as the key
+ chunkIDs map[chunkMessageID][]*messageID
+ pc *partitionConsumer
+ mu sync.Mutex
+}
+
+func newUnAckChunksTracker(pc *partitionConsumer) *unAckChunksTracker {
+ return &unAckChunksTracker{
+ chunkIDs: make(map[chunkMessageID][]*messageID),
+ pc: pc,
+ }
+}
+
+func (u *unAckChunksTracker) add(cmid *chunkMessageID, ids []*messageID) {
+ u.mu.Lock()
+ defer u.mu.Unlock()
+
+ u.chunkIDs[*cmid] = ids
+}
+
+func (u *unAckChunksTracker) get(cmid *chunkMessageID) []*messageID {
+ u.mu.Lock()
+ defer u.mu.Unlock()
+
+ return u.chunkIDs[*cmid]
+}
+
+func (u *unAckChunksTracker) remove(cmid *chunkMessageID) {
+ u.mu.Lock()
+ defer u.mu.Unlock()
+
+ delete(u.chunkIDs, *cmid)
+}
+
+func (u *unAckChunksTracker) ack(cmid *chunkMessageID) error {
+ ids := u.get(cmid)
+ for _, id := range ids {
+ if err := u.pc.AckID(id); err != nil {
+ return err
+ }
+ }
+ u.remove(cmid)
+ return nil
+}
+
+func (u *unAckChunksTracker) nack(cmid *chunkMessageID) {
+ ids := u.get(cmid)
+ for _, id := range ids {
+ u.pc.NackID(id)
+ }
+ u.remove(cmid)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_regex.go b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_regex.go
new file mode 100644
index 00000000..2520af5c
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/consumer_regex.go
@@ -0,0 +1,488 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "regexp"
+ "strings"
+ "sync"
+ "time"
+
+ pkgerrors "github.com/pkg/errors"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+const (
+ defaultAutoDiscoveryDuration = 1 * time.Minute
+)
+
+type regexConsumer struct {
+ client *client
+ dlq *dlqRouter
+ rlq *retryRouter
+
+ options ConsumerOptions
+
+ messageCh chan ConsumerMessage
+
+ namespace string
+ pattern *regexp.Regexp
+
+ consumersLock sync.Mutex
+ consumers map[string]Consumer
+ subscribeCh chan []string
+ unsubscribeCh chan []string
+
+ closeOnce sync.Once
+ closeCh chan struct{}
+
+ ticker *time.Ticker
+
+ log log.Logger
+
+ consumerName string
+}
+
+func newRegexConsumer(c *client, opts ConsumerOptions, tn *internal.TopicName, pattern *regexp.Regexp,
+ msgCh chan ConsumerMessage, dlq *dlqRouter, rlq *retryRouter) (Consumer, error) {
+ rc := ®exConsumer{
+ client: c,
+ dlq: dlq,
+ rlq: rlq,
+ options: opts,
+ messageCh: msgCh,
+
+ namespace: tn.Namespace,
+ pattern: pattern,
+
+ consumers: make(map[string]Consumer),
+ subscribeCh: make(chan []string, 1),
+ unsubscribeCh: make(chan []string, 1),
+
+ closeCh: make(chan struct{}),
+
+ log: c.log.SubLogger(log.Fields{"topic": tn.Name}),
+ consumerName: opts.Name,
+ }
+
+ topics, err := rc.topics()
+ if err != nil {
+ return nil, err
+ }
+
+ var errs error
+ for ce := range subscriber(c, topics, opts, msgCh, dlq, rlq) {
+ if ce.err != nil {
+ errs = pkgerrors.Wrapf(ce.err, "unable to subscribe to topic=%s", ce.topic)
+ } else {
+ rc.consumers[ce.topic] = ce.consumer
+ }
+ }
+
+ if errs != nil {
+ for _, c := range rc.consumers {
+ c.Close()
+ }
+ return nil, errs
+ }
+
+ // set up timer
+ duration := opts.AutoDiscoveryPeriod
+ if duration <= 0 {
+ duration = defaultAutoDiscoveryDuration
+ }
+ rc.ticker = time.NewTicker(duration)
+
+ go rc.monitor()
+
+ return rc, nil
+}
+
+func (c *regexConsumer) Subscription() string {
+ return c.options.SubscriptionName
+}
+
+func (c *regexConsumer) Unsubscribe() error {
+ var errs error
+ c.consumersLock.Lock()
+ defer c.consumersLock.Unlock()
+
+ for topic, consumer := range c.consumers {
+ if err := consumer.Unsubscribe(); err != nil {
+ msg := fmt.Sprintf("unable to unsubscribe from topic=%s subscription=%s",
+ topic, c.Subscription())
+ errs = pkgerrors.Wrap(err, msg)
+ }
+ }
+ return errs
+}
+
+func (c *regexConsumer) Receive(ctx context.Context) (message Message, err error) {
+ for {
+ select {
+ case <-c.closeCh:
+ return nil, newError(ConsumerClosed, "consumer closed")
+ case cm, ok := <-c.messageCh:
+ if !ok {
+ return nil, newError(ConsumerClosed, "consumer closed")
+ }
+ return cm.Message, nil
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+}
+
+// Chan return the messages chan to user
+func (c *regexConsumer) Chan() <-chan ConsumerMessage {
+ return c.messageCh
+}
+
+// Ack the consumption of a single message
+func (c *regexConsumer) Ack(msg Message) error {
+ return c.AckID(msg.ID())
+}
+
+func (c *regexConsumer) ReconsumeLater(msg Message, delay time.Duration) {
+ c.log.Warnf("regexp consumer not support ReconsumeLater yet.")
+}
+
+func (c *regexConsumer) ReconsumeLaterWithCustomProperties(msg Message, customProperties map[string]string,
+ delay time.Duration) {
+ c.log.Warnf("regexp consumer not support ReconsumeLaterWithCustomProperties yet.")
+}
+
+// AckID the consumption of a single message, identified by its MessageID
+func (c *regexConsumer) AckID(msgID MessageID) error {
+ if !checkMessageIDType(msgID) {
+ c.log.Warnf("invalid message id type %T", msgID)
+ return fmt.Errorf("invalid message id type %T", msgID)
+ }
+
+ mid := toTrackingMessageID(msgID)
+
+ if mid.consumer == nil {
+ c.log.Warnf("unable to ack messageID=%+v can not determine topic", msgID)
+ return errors.New("consumer is nil in consumer_regex")
+ }
+
+ if c.options.AckWithResponse {
+ return mid.consumer.AckIDWithResponse(msgID)
+ }
+
+ return mid.consumer.AckID(msgID)
+}
+
+// AckCumulative the reception of all the messages in the stream up to (and including)
+// the provided message.
+func (c *regexConsumer) AckCumulative(msg Message) error {
+ return c.AckIDCumulative(msg.ID())
+}
+
+// AckIDCumulative the reception of all the messages in the stream up to (and including)
+// the provided message, identified by its MessageID
+func (c *regexConsumer) AckIDCumulative(msgID MessageID) error {
+ if !checkMessageIDType(msgID) {
+ c.log.Warnf("invalid message id type %T", msgID)
+ return fmt.Errorf("invalid message id type %T", msgID)
+ }
+
+ mid := toTrackingMessageID(msgID)
+
+ if mid.consumer == nil {
+ c.log.Warnf("unable to ack messageID=%+v can not determine topic", msgID)
+ return errors.New("unable to ack message because consumer is nil")
+ }
+
+ if c.options.AckWithResponse {
+ return mid.consumer.AckIDWithResponseCumulative(msgID)
+ }
+
+ return mid.consumer.AckIDCumulative(msgID)
+}
+
+func (c *regexConsumer) Nack(msg Message) {
+ if c.options.EnableDefaultNackBackoffPolicy || c.options.NackBackoffPolicy != nil {
+ msgID := msg.ID()
+ if !checkMessageIDType(msgID) {
+ c.log.Warnf("invalid message id type %T", msgID)
+ return
+ }
+ mid := toTrackingMessageID(msgID)
+
+ if mid.consumer == nil {
+ c.log.Warnf("unable to nack messageID=%+v can not determine topic", msgID)
+ return
+ }
+ mid.NackByMsg(msg)
+ return
+ }
+
+ c.NackID(msg.ID())
+}
+
+func (c *regexConsumer) NackID(msgID MessageID) {
+ if !checkMessageIDType(msgID) {
+ c.log.Warnf("invalid message id type %T", msgID)
+ return
+ }
+
+ mid := toTrackingMessageID(msgID)
+
+ if mid.consumer == nil {
+ c.log.Warnf("unable to nack messageID=%+v can not determine topic", msgID)
+ return
+ }
+
+ mid.consumer.NackID(msgID)
+}
+
+func (c *regexConsumer) Close() {
+ c.closeOnce.Do(func() {
+ c.ticker.Stop()
+ close(c.closeCh)
+
+ var wg sync.WaitGroup
+ c.consumersLock.Lock()
+ defer c.consumersLock.Unlock()
+ wg.Add(len(c.consumers))
+ for _, con := range c.consumers {
+ go func(consumer Consumer) {
+ defer wg.Done()
+ consumer.Close()
+ }(con)
+ }
+ wg.Wait()
+ c.client.handlers.Del(c)
+ c.dlq.close()
+ c.rlq.close()
+ })
+}
+
+func (c *regexConsumer) Seek(msgID MessageID) error {
+ return newError(SeekFailed, "seek command not allowed for regex consumer")
+}
+
+func (c *regexConsumer) SeekByTime(time time.Time) error {
+ return newError(SeekFailed, "seek command not allowed for regex consumer")
+}
+
+// Name returns the name of consumer.
+func (c *regexConsumer) Name() string {
+ return c.consumerName
+}
+
+func (c *regexConsumer) closed() bool {
+ select {
+ case <-c.closeCh:
+ return true
+ default:
+ return false
+ }
+}
+
+func (c *regexConsumer) monitor() {
+ for {
+ select {
+ case <-c.closeCh:
+ return
+ case <-c.ticker.C:
+ c.log.Debug("Auto discovering topics")
+ if !c.closed() {
+ c.discover()
+ }
+ case topics := <-c.subscribeCh:
+ if len(topics) > 0 && !c.closed() {
+ c.subscribe(topics, c.dlq, c.rlq)
+ }
+ case topics := <-c.unsubscribeCh:
+ if len(topics) > 0 && !c.closed() {
+ c.unsubscribe(topics)
+ }
+ }
+ }
+}
+
+func (c *regexConsumer) discover() {
+ topics, err := c.topics()
+ if err != nil {
+ c.log.WithError(err).Errorf("Failed to discover topics")
+ return
+ }
+ known := c.knownTopics()
+ newTopics := topicsDiff(topics, known)
+ staleTopics := topicsDiff(known, topics)
+
+ c.log.
+ WithFields(log.Fields{
+ "new_topics": newTopics,
+ "old_topics": staleTopics,
+ }).
+ Debug("discover topics")
+
+ c.unsubscribeCh <- staleTopics
+ c.subscribeCh <- newTopics
+}
+
+func (c *regexConsumer) knownTopics() []string {
+ c.consumersLock.Lock()
+ defer c.consumersLock.Unlock()
+ topics := make([]string, len(c.consumers))
+ n := 0
+ for t := range c.consumers {
+ topics[n] = t
+ n++
+ }
+
+ return topics
+}
+
+func (c *regexConsumer) subscribe(topics []string, dlq *dlqRouter, rlq *retryRouter) {
+ c.log.WithField("topics", topics).Debug("subscribe")
+ consumers := make(map[string]Consumer, len(topics))
+ for ce := range subscriber(c.client, topics, c.options, c.messageCh, dlq, rlq) {
+ if ce.err != nil {
+ c.log.Warnf("Failed to subscribe to topic=%s", ce.topic)
+ } else {
+ consumers[ce.topic] = ce.consumer
+ }
+ }
+
+ c.consumersLock.Lock()
+ defer c.consumersLock.Unlock()
+ for t, consumer := range consumers {
+ c.consumers[t] = consumer
+ }
+}
+
+func (c *regexConsumer) unsubscribe(topics []string) {
+ c.log.WithField("topics", topics).Debug("unsubscribe")
+
+ consumers := make(map[string]Consumer, len(topics))
+ c.consumersLock.Lock()
+
+ for _, t := range topics {
+ if consumer, ok := c.consumers[t]; ok {
+ consumers[t] = consumer
+ delete(c.consumers, t)
+ }
+ }
+ c.consumersLock.Unlock()
+
+ for t, consumer := range consumers {
+ c.log.Debugf("unsubscribe from topic=%s subscription=%s", t, c.options.SubscriptionName)
+ if err := consumer.Unsubscribe(); err != nil {
+ c.log.Warnf("unable to unsubscribe from topic=%s subscription=%s",
+ t, c.options.SubscriptionName)
+ }
+ consumer.Close()
+ }
+}
+
+func (c *regexConsumer) topics() ([]string, error) {
+ topics, err := c.client.lookupService.GetTopicsOfNamespace(c.namespace, internal.Persistent)
+ if err != nil {
+ return nil, err
+ }
+
+ filtered := filterTopics(topics, c.pattern)
+ return filtered, nil
+}
+
+type consumerError struct {
+ err error
+ topic string
+ consumer Consumer
+}
+
+func subscriber(c *client, topics []string, opts ConsumerOptions, ch chan ConsumerMessage,
+ dlq *dlqRouter, rlq *retryRouter) <-chan consumerError {
+ consumerErrorCh := make(chan consumerError, len(topics))
+ var wg sync.WaitGroup
+ wg.Add(len(topics))
+ go func() {
+ wg.Wait()
+ close(consumerErrorCh)
+ }()
+
+ for _, t := range topics {
+ go func(topic string) {
+ defer wg.Done()
+ c, err := newInternalConsumer(c, opts, topic, ch, dlq, rlq, true)
+ consumerErrorCh <- consumerError{
+ err: err,
+ topic: topic,
+ consumer: c,
+ }
+ }(t)
+ }
+
+ return consumerErrorCh
+}
+
+func filterTopics(topics []string, regex *regexp.Regexp) []string {
+ matches := make(map[string]bool)
+ matching := make([]string, 0)
+ for _, t := range topics {
+ tn, _ := internal.ParseTopicName(t)
+ topic := internal.TopicNameWithoutPartitionPart(tn)
+ if _, ok := matches[topic]; ok {
+ continue
+ }
+ if regex.MatchString(topic) {
+ matches[topic] = true
+ matching = append(matching, topic)
+ }
+ }
+
+ return matching
+}
+
+// topicDiff returns all topics in topics1 that are not in topics2
+func topicsDiff(topics1 []string, topics2 []string) []string {
+ if len(topics2) == 0 {
+ return topics1
+ }
+ diff := make([]string, 0)
+ topics := make(map[string]bool, len(topics2))
+ for _, t := range topics2 {
+ topics[t] = true
+ }
+
+ for _, t := range topics1 {
+ if !topics[t] {
+ diff = append(diff, t)
+ }
+ }
+
+ return diff
+}
+
+func extractTopicPattern(tn *internal.TopicName) (*regexp.Regexp, error) {
+ idx := strings.Index(tn.Name, tn.Namespace)
+ if idx > 0 {
+ return regexp.Compile(tn.Name[idx:])
+ }
+
+ return regexp.Compile(tn.Name)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/crypto_failure_action.go b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/crypto_failure_action.go
new file mode 100644
index 00000000..0bdd289d
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/crypto_failure_action.go
@@ -0,0 +1,43 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+const (
+ // ProducerCryptoFailureActionFail this is the default option to fail send if crypto operation fails.
+ ProducerCryptoFailureActionFail = iota
+
+ // ProducerCryptoFailureActionSend ignore crypto failure and proceed with sending unencrypted message.
+ ProducerCryptoFailureActionSend
+)
+
+const (
+ // ConsumerCryptoFailureActionFail this is the default option to fail consume messages until crypto succeeds.
+ ConsumerCryptoFailureActionFail = iota
+
+ // ConsumerCryptoFailureActionDiscard message is silently acknowledged and not delivered to the application
+ ConsumerCryptoFailureActionDiscard
+
+ // ConsumerCryptoFailureActionConsume deliver the encrypted message to the application.
+ // It's the application's responsibility to decrypt the message.
+ // if message is also compressed, decompression will fail.
+ // If message contain batch messages, client will not be able to retrieve
+ // individual messages in the batch.
+ // delivered encrypted message contains EncryptionContext which contains encryption
+ // and compression information in it using which application can decrypt the payload.
+ ConsumerCryptoFailureActionConsume
+)
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/crypto_key_reader.go b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/crypto_key_reader.go
new file mode 100644
index 00000000..51295c13
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/crypto_key_reader.go
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+// KeyReader implement this interface to read and provide public & private keys
+// key pair can be RSA, ECDSA
+type KeyReader interface {
+ // PublicKey get public key that is be used by the producer to encrypt data key
+ PublicKey(keyName string, metadata map[string]string) (*EncryptionKeyInfo, error)
+
+ // PrivateKey get private key that is used by the consumer to decrypt data key
+ PrivateKey(keyName string, metadata map[string]string) (*EncryptionKeyInfo, error)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/default_crypto_Key_reader.go b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/default_crypto_Key_reader.go
new file mode 100644
index 00000000..8dfb2bc0
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/default_crypto_Key_reader.go
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import "os"
+
+// FileKeyReader default implementation of KeyReader
+type FileKeyReader struct {
+ publicKeyPath string
+ privateKeyPath string
+}
+
+func NewFileKeyReader(publicKeyPath, privateKeyPath string) *FileKeyReader {
+ return &FileKeyReader{
+ publicKeyPath: publicKeyPath,
+ privateKeyPath: privateKeyPath,
+ }
+}
+
+// PublicKey read public key from the given path
+func (d *FileKeyReader) PublicKey(keyName string, keyMeta map[string]string) (*EncryptionKeyInfo, error) {
+ return readKey(keyName, d.publicKeyPath, keyMeta)
+}
+
+// PrivateKey read private key from the given path
+func (d *FileKeyReader) PrivateKey(keyName string, keyMeta map[string]string) (*EncryptionKeyInfo, error) {
+ return readKey(keyName, d.privateKeyPath, keyMeta)
+}
+
+func readKey(keyName, path string, keyMeta map[string]string) (*EncryptionKeyInfo, error) {
+ key, err := os.ReadFile(path)
+ if err != nil {
+ return nil, err
+ }
+ return NewEncryptionKeyInfo(keyName, key, keyMeta), nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/default_message_crypto.go b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/default_message_crypto.go
new file mode 100644
index 00000000..74e4592d
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/default_message_crypto.go
@@ -0,0 +1,365 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import (
+ gocrypto "crypto"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/md5"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha1"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "sync"
+
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+// DefaultMessageCrypto implementation of the interface MessageCryto
+type DefaultMessageCrypto struct {
+ // data key which is used to encrypt/decrypt messages
+ dataKey []byte
+
+ // LoadingCache used by the consumer to cache already decrypted key
+ loadingCache sync.Map // map[string][]byte
+
+ encryptedDataKeyMap sync.Map // map[string]EncryptionKeyInfo
+
+ logCtx string
+
+ logger log.Logger
+
+ cipherLock sync.Mutex
+
+ encryptLock sync.Mutex
+}
+
+// NewDefaultMessageCrypto get the instance of message crypto
+func NewDefaultMessageCrypto(logCtx string, keyGenNeeded bool, logger log.Logger) (*DefaultMessageCrypto, error) {
+
+ d := &DefaultMessageCrypto{
+ logCtx: logCtx,
+ loadingCache: sync.Map{},
+ encryptedDataKeyMap: sync.Map{},
+ logger: logger,
+ }
+
+ if keyGenNeeded {
+ key, err := generateDataKey()
+ if err != nil {
+ return d, err
+ }
+ d.dataKey = key
+ }
+
+ return d, nil
+}
+
+// AddPublicKeyCipher encrypt data key using keyCrypto and cache
+func (d *DefaultMessageCrypto) AddPublicKeyCipher(keyNames []string, keyReader KeyReader) error {
+ key, err := generateDataKey()
+ if err != nil {
+ return err
+ }
+
+ d.dataKey = key
+ for _, keyName := range keyNames {
+ err := d.addPublicKeyCipher(keyName, keyReader)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (d *DefaultMessageCrypto) addPublicKeyCipher(keyName string, keyReader KeyReader) error {
+ d.cipherLock.Lock()
+ defer d.cipherLock.Unlock()
+ if keyName == "" || keyReader == nil {
+ return fmt.Errorf("keyname or keyreader is null")
+ }
+
+ // read the public key and its info using keyReader
+ keyInfo, err := keyReader.PublicKey(keyName, nil)
+ if err != nil {
+ return err
+ }
+
+ parsedKey, err := d.loadPublicKey(keyInfo.Key())
+ if err != nil {
+ return err
+ }
+
+ // try to cast to RSA key
+ rsaPubKey, ok := parsedKey.(*rsa.PublicKey)
+ if !ok {
+ return fmt.Errorf("only RSA keys are supported")
+ }
+
+ encryptedDataKey, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, rsaPubKey, d.dataKey, nil)
+ if err != nil {
+ return err
+ }
+
+ d.encryptedDataKeyMap.Store(keyName, NewEncryptionKeyInfo(keyName, encryptedDataKey, keyInfo.Metadata()))
+
+ return nil
+}
+
+// RemoveKeyCipher remove encrypted data key from cache
+func (d *DefaultMessageCrypto) RemoveKeyCipher(keyName string) bool {
+ if keyName == "" {
+ return false
+ }
+ d.encryptedDataKeyMap.Delete(keyName)
+ return true
+}
+
+// Encrypt payload using encryption keys and add encrypted data key
+// to message metadata. Here data key is encrypted
+// using public key
+func (d *DefaultMessageCrypto) Encrypt(encKeys []string,
+ keyReader KeyReader,
+ msgMetadata MessageMetadataSupplier,
+ payload []byte) ([]byte, error) {
+ d.encryptLock.Lock()
+ defer d.encryptLock.Unlock()
+
+ if len(encKeys) == 0 {
+ return payload, nil
+ }
+
+ for _, keyName := range encKeys {
+ // if key is not already loaded, load it
+ if _, ok := d.encryptedDataKeyMap.Load(keyName); !ok {
+ if err := d.addPublicKeyCipher(keyName, keyReader); err != nil {
+ d.logger.Error(err)
+ }
+ }
+
+ // add key to the message metadata
+ if k, ok := d.encryptedDataKeyMap.Load(keyName); ok {
+ keyInfo, keyInfoOk := k.(*EncryptionKeyInfo)
+
+ if keyInfoOk {
+ msgMetadata.UpsertEncryptionKey(*keyInfo)
+ } else {
+ d.logger.Error("failed to get EncryptionKeyInfo for key %v", keyName)
+ }
+ } else {
+ // we should never reach here
+ msg := fmt.Sprintf("%v Failed to find encrypted Data key for key %v", d.logCtx, keyName)
+ d.logger.Errorf(msg)
+ return nil, fmt.Errorf(msg)
+ }
+
+ }
+
+ // generate a new AES cipher with data key
+ c, err := aes.NewCipher(d.dataKey)
+
+ if err != nil {
+ d.logger.Error("failed to create AES cipher")
+ return nil, err
+ }
+
+ // gcm
+ gcm, err := cipher.NewGCM(c)
+
+ if err != nil {
+ d.logger.Error("failed to create gcm")
+ return nil, err
+ }
+
+ // create gcm param
+ nonce := make([]byte, gcm.NonceSize())
+ _, err = rand.Read(nonce)
+
+ if err != nil {
+ d.logger.Error(err)
+ return nil, err
+ }
+
+ // Update message metadata with encryption param
+ msgMetadata.SetEncryptionParam(nonce)
+
+ // encrypt payload using seal function
+ return gcm.Seal(nil, nonce, payload, nil), nil
+}
+
+// Decrypt the payload using decrypted data key.
+// Here data key is read from the message
+// metadata and decrypted using private key.
+func (d *DefaultMessageCrypto) Decrypt(msgMetadata MessageMetadataSupplier,
+ payload []byte,
+ keyReader KeyReader) ([]byte, error) {
+ // if data key is present, attempt to derypt using the existing key
+ if d.dataKey != nil {
+ decryptedData, err := d.getKeyAndDecryptData(msgMetadata, payload)
+ if err != nil {
+ d.logger.Error(err)
+ }
+
+ if decryptedData != nil {
+ return decryptedData, nil
+ }
+ }
+
+ // data key is null or decryption failed. Attempt to regenerate data key
+ encKeys := msgMetadata.EncryptionKeys()
+ var ecKeyInfo *EncryptionKeyInfo
+
+ for _, encKey := range encKeys {
+ if d.decryptDataKey(encKey.Name(), encKey.Key(), encKey.Metadata(), keyReader) {
+ ecKeyInfo = &encKey
+ }
+ }
+
+ if ecKeyInfo == nil || d.dataKey == nil {
+ // unable to decrypt data key
+ return nil, errors.New("unable to decrypt data key")
+ }
+
+ return d.getKeyAndDecryptData(msgMetadata, payload)
+}
+
+func (d *DefaultMessageCrypto) decryptData(dataKeySecret []byte,
+ msgMetadata MessageMetadataSupplier,
+ payload []byte) ([]byte, error) {
+ // get nonce from message metadata
+ nonce := msgMetadata.EncryptionParam()
+
+ c, err := aes.NewCipher(dataKeySecret)
+
+ if err != nil {
+ d.logger.Error(err)
+ return nil, err
+ }
+
+ gcm, err := cipher.NewGCM(c)
+ if err != nil {
+ return nil, err
+ }
+
+ decryptedData, err := gcm.Open(nil, nonce, payload, nil)
+
+ if err != nil {
+ d.logger.Error(err)
+ }
+
+ return decryptedData, err
+}
+
+func (d *DefaultMessageCrypto) getKeyAndDecryptData(msgMetadata MessageMetadataSupplier,
+ payload []byte) ([]byte, error) {
+ // go through all keys to retrieve data key from cache
+ for _, k := range msgMetadata.EncryptionKeys() {
+ msgDataKey := k.Key()
+ keyDigest := fmt.Sprintf("%x", md5.Sum(msgDataKey))
+ if storedSecretKey, ok := d.loadingCache.Load(keyDigest); ok {
+ decryptedData, err := d.decryptData(storedSecretKey.([]byte), msgMetadata, payload)
+ if err != nil {
+ d.logger.Error(err)
+ }
+
+ if decryptedData != nil {
+ return decryptedData, nil
+ }
+ } else {
+ // First time, entry won't be present in cache
+ d.logger.Debugf("%s Failed to decrypt data or data key is not in cache. Will attempt to refresh", d.logCtx)
+ }
+ }
+ return nil, nil
+}
+
+func (d *DefaultMessageCrypto) decryptDataKey(keyName string,
+ encDatakey []byte,
+ keyMeta map[string]string,
+ keyReader KeyReader) bool {
+
+ keyInfo, err := keyReader.PrivateKey(keyName, keyMeta)
+ if err != nil {
+ d.logger.Error(err)
+ return false
+ }
+
+ parsedKey, err := d.loadPrivateKey(keyInfo.Key())
+ if err != nil {
+ d.logger.Error(err)
+ return false
+ }
+
+ rsaPriKey, ok := parsedKey.(*rsa.PrivateKey)
+ if !ok {
+ d.logger.Error("only RSA keys are supported")
+ return false
+ }
+
+ decryptedDataKey, err := rsa.DecryptOAEP(sha1.New(), rand.Reader, rsaPriKey, encDatakey, nil)
+ if err != nil {
+ d.logger.Error(err)
+ return false
+ }
+ d.dataKey = decryptedDataKey
+ d.loadingCache.Store(fmt.Sprintf("%x", md5.Sum(encDatakey)), d.dataKey)
+
+ return true
+}
+
+func (d *DefaultMessageCrypto) loadPrivateKey(key []byte) (gocrypto.PrivateKey, error) {
+ var privateKey gocrypto.PrivateKey
+ priPem, _ := pem.Decode(key)
+ if priPem == nil {
+ return privateKey, fmt.Errorf("failed to decode private key")
+ }
+ genericPrivateKey, err := x509.ParsePKCS1PrivateKey(priPem.Bytes)
+ if err != nil {
+ return privateKey, err
+ }
+ privateKey = genericPrivateKey
+ return privateKey, nil
+}
+
+// read the public key into RSA key
+func (d *DefaultMessageCrypto) loadPublicKey(key []byte) (gocrypto.PublicKey, error) {
+ var publickKey gocrypto.PublicKey
+
+ pubPem, _ := pem.Decode(key)
+ if pubPem == nil {
+ return publickKey, fmt.Errorf("failed to decode public key")
+ }
+
+ genericPublicKey, err := x509.ParsePKIXPublicKey(pubPem.Bytes)
+ if err != nil {
+ return publickKey, err
+ }
+ publickKey = genericPublicKey
+
+ return publickKey, nil
+}
+
+func generateDataKey() ([]byte, error) {
+ key := make([]byte, 32) // generate key of length 256 bits
+ _, err := rand.Read(key) // cryptographically secure random number
+ return key, err
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/encryption_key_Info.go b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/encryption_key_Info.go
new file mode 100644
index 00000000..11dd4449
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/encryption_key_Info.go
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+// EncryptionKeyInfo
+type EncryptionKeyInfo struct {
+ metadata map[string]string
+ key []byte
+ name string
+}
+
+// NewEncryptionKeyInfo create a new EncryptionKeyInfo
+func NewEncryptionKeyInfo(name string, key []byte, metadata map[string]string) *EncryptionKeyInfo {
+ return &EncryptionKeyInfo{
+ metadata: metadata,
+ name: name,
+ key: key,
+ }
+}
+
+// Name get the name of the key
+func (eci *EncryptionKeyInfo) Name() string {
+ return eci.name
+}
+
+// Key get the key data
+func (eci *EncryptionKeyInfo) Key() []byte {
+ return eci.key
+}
+
+// Metadata get key metadata
+func (eci *EncryptionKeyInfo) Metadata() map[string]string {
+ return eci.metadata
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/message_crypto.go b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/message_crypto.go
new file mode 100644
index 00000000..4a17b71d
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/message_crypto.go
@@ -0,0 +1,39 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+// MessageCrypto implement this interface to encrypt and decrypt messages
+type MessageCrypto interface {
+
+ // AddPublicKeyCipher encrypt data using the public key(s) in the argument.
+ // If more than one key name is specified, data key is encrypted using each of those keys.
+ // If the public key is expired or changed, application is responsible to remove
+ // the old key and add the new key.
+ AddPublicKeyCipher(keyNames []string, keyReader KeyReader) error
+
+ // RemoveKeyCipher remove the key from the list
+ RemoveKeyCipher(keyName string) bool
+
+ // Encrypt the payload using the data key and update
+ // message metadata with the key and encrypted data key
+ Encrypt(encKeys []string, KeyReader KeyReader, msgMetadata MessageMetadataSupplier, payload []byte) ([]byte, error)
+
+ // Decrypt the payload using the data key.
+ // Keys used to encrypt the data key can be retrieved from msgMetadata
+ Decrypt(msgMetadata MessageMetadataSupplier, payload []byte, KeyReader KeyReader) ([]byte, error)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/message_metadata.go b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/message_metadata.go
new file mode 100644
index 00000000..717b0c0a
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/crypto/message_metadata.go
@@ -0,0 +1,122 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import (
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+// MessageMetadataSupplier wrapper implementation around message metadata
+type MessageMetadataSupplier interface {
+ // EncryptionKeys read all the encryption keys from the MessageMetadata
+ EncryptionKeys() []EncryptionKeyInfo
+
+ // UpsertEncryptionKey add new or update existing EncryptionKeys in to the MessageMetadata
+ UpsertEncryptionKey(EncryptionKeyInfo)
+
+ // EncryptionParam read the ecryption parameter from the MessageMetadata
+ EncryptionParam() []byte
+
+ // SetEncryptionParam set encryption parameter in to the MessageMetadata
+ SetEncryptionParam([]byte)
+}
+
+type MessageMetadata struct {
+ messageMetadata *pb.MessageMetadata
+}
+
+func NewMessageMetadataSupplier(messageMetadata *pb.MessageMetadata) MessageMetadataSupplier {
+ return &MessageMetadata{
+ messageMetadata: messageMetadata,
+ }
+}
+
+func (m *MessageMetadata) EncryptionKeys() []EncryptionKeyInfo {
+ if m.messageMetadata != nil {
+ encInfo := []EncryptionKeyInfo{}
+ for _, k := range m.messageMetadata.EncryptionKeys {
+ key := NewEncryptionKeyInfo(k.GetKey(), k.GetValue(), getKeyMetaMap(k.GetMetadata()))
+ encInfo = append(encInfo, *key)
+ }
+ return encInfo
+ }
+ return nil
+}
+
+func (m *MessageMetadata) UpsertEncryptionKey(keyInfo EncryptionKeyInfo) {
+ if m.messageMetadata != nil {
+ idx := m.encryptionKeyPresent(keyInfo)
+ newKey := &pb.EncryptionKeys{
+ Key: &keyInfo.name,
+ Value: keyInfo.Key(),
+ Metadata: getKeyMeta(keyInfo.Metadata()),
+ }
+
+ if idx >= 0 {
+ m.messageMetadata.EncryptionKeys[idx] = newKey
+ } else {
+ m.messageMetadata.EncryptionKeys = append(m.messageMetadata.EncryptionKeys, newKey)
+ }
+ }
+}
+
+func (m *MessageMetadata) EncryptionParam() []byte {
+ if m.messageMetadata != nil {
+ return m.messageMetadata.EncryptionParam
+ }
+ return nil
+}
+
+func (m *MessageMetadata) SetEncryptionParam(param []byte) {
+ if m.messageMetadata != nil {
+ m.messageMetadata.EncryptionParam = param
+ }
+}
+
+func (m *MessageMetadata) encryptionKeyPresent(keyInfo EncryptionKeyInfo) int {
+ if len(m.messageMetadata.EncryptionKeys) > 0 {
+ for idx, k := range m.messageMetadata.EncryptionKeys {
+ if k.GetKey() == keyInfo.Name() {
+ return idx
+ }
+ }
+ }
+ return -1
+}
+
+func getKeyMeta(metaMap map[string]string) []*pb.KeyValue {
+ if len(metaMap) > 0 {
+ var meta []*pb.KeyValue
+ for k, v := range metaMap {
+ meta = append(meta, &pb.KeyValue{Key: &k, Value: &v})
+ }
+ return meta
+ }
+ return nil
+}
+
+func getKeyMetaMap(keyValues []*pb.KeyValue) map[string]string {
+ if keyValues != nil {
+ meta := map[string]string{}
+ for _, kv := range keyValues {
+ meta[kv.GetKey()] = kv.GetValue()
+ }
+ return meta
+ }
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/default_router.go b/vendor/github.com/apache/pulsar-client-go/pulsar/default_router.go
new file mode 100644
index 00000000..6945ff19
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/default_router.go
@@ -0,0 +1,111 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "math/rand"
+ "sync/atomic"
+ "time"
+)
+
+type defaultRouter struct {
+ currentPartitionCursor uint32
+
+ lastBatchTimestamp int64
+ msgCounter uint32
+ cumulativeBatchSize uint32
+}
+
+// NewDefaultRouter set the message routing mode for the partitioned producer.
+// Default routing mode is round-robin routing if no partition key is specified.
+// If the batching is enabled, it honors the different thresholds for batching i.e. maximum batch size,
+// maximum number of messages, maximum delay to publish a batch. When one of the threshold is reached the next partition
+// is used.
+func NewDefaultRouter(
+ hashFunc func(string) uint32,
+ maxBatchingMessages uint,
+ maxBatchingSize uint,
+ maxBatchingDelay time.Duration,
+ disableBatching bool) func(*ProducerMessage, uint32) int {
+ state := &defaultRouter{
+ currentPartitionCursor: rand.Uint32(),
+ lastBatchTimestamp: time.Now().UnixNano(),
+ }
+
+ readClockAfterNumMessages := uint32(maxBatchingMessages / 10)
+ return func(message *ProducerMessage, numPartitions uint32) int {
+ if numPartitions == 1 {
+ // When there are no partitions, don't even bother
+ return 0
+ }
+
+ if len(message.OrderingKey) != 0 {
+ // When an OrderingKey is specified, use the hash of that key
+ return int(hashFunc(message.OrderingKey) % numPartitions)
+ }
+
+ if len(message.Key) != 0 {
+ // When a key is specified, use the hash of that key
+ return int(hashFunc(message.Key) % numPartitions)
+ }
+
+ // If there's no key, we do round-robin across partition. If no batching go to next partition.
+ if disableBatching {
+ p := int(state.currentPartitionCursor % numPartitions)
+ atomic.AddUint32(&state.currentPartitionCursor, 1)
+ return p
+ }
+
+ // If there's no key, we do round-robin across partition, sticking with a given
+ // partition for a certain amount of messages or volume buffered or the max delay to batch is reached so that
+ // we ensure having a decent amount of batching of the messages.
+ var now int64
+ size := uint32(len(message.Payload))
+ partitionCursor := atomic.LoadUint32(&state.currentPartitionCursor)
+ messageCount := atomic.AddUint32(&state.msgCounter, 1)
+ batchSize := atomic.AddUint32(&state.cumulativeBatchSize, size)
+
+ // Note: use greater-than for the threshold check so that we don't route this message to a new partition
+ // before a batch is complete.
+ messageCountReached := messageCount > uint32(maxBatchingMessages)
+ sizeReached := batchSize > uint32(maxBatchingSize)
+ durationReached := false
+ if readClockAfterNumMessages == 0 || messageCount%readClockAfterNumMessages == 0 {
+ now = time.Now().UnixNano()
+ lastBatchTime := atomic.LoadInt64(&state.lastBatchTimestamp)
+ durationReached = now-lastBatchTime > maxBatchingDelay.Nanoseconds()
+ }
+ if messageCountReached || sizeReached || durationReached {
+ // Note: CAS to ensure that concurrent go-routines can only move the cursor forward by one so that
+ // partitions are not skipped.
+ newCursor := partitionCursor + 1
+ if atomic.CompareAndSwapUint32(&state.currentPartitionCursor, partitionCursor, newCursor) {
+ atomic.StoreUint32(&state.msgCounter, 0)
+ atomic.StoreUint32(&state.cumulativeBatchSize, 0)
+ if now == 0 {
+ now = time.Now().UnixNano()
+ }
+ atomic.StoreInt64(&state.lastBatchTimestamp, now)
+ }
+
+ return int(newCursor % numPartitions)
+ }
+
+ return int(partitionCursor % numPartitions)
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/dlq_router.go b/vendor/github.com/apache/pulsar-client-go/pulsar/dlq_router.go
new file mode 100644
index 00000000..6d300036
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/dlq_router.go
@@ -0,0 +1,172 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+type dlqRouter struct {
+ client Client
+ producer Producer
+ policy *DLQPolicy
+ messageCh chan ConsumerMessage
+ closeCh chan interface{}
+ log log.Logger
+}
+
+func newDlqRouter(client Client, policy *DLQPolicy, logger log.Logger) (*dlqRouter, error) {
+ r := &dlqRouter{
+ client: client,
+ policy: policy,
+ log: logger,
+ }
+
+ if policy != nil {
+ if policy.MaxDeliveries <= 0 {
+ return nil, newError(InvalidConfiguration, "DLQPolicy.MaxDeliveries needs to be > 0")
+ }
+
+ if policy.DeadLetterTopic == "" {
+ return nil, newError(InvalidConfiguration, "DLQPolicy.Topic needs to be set to a valid topic name")
+ }
+
+ r.messageCh = make(chan ConsumerMessage)
+ r.closeCh = make(chan interface{}, 1)
+ r.log = logger.SubLogger(log.Fields{"dlq-topic": policy.DeadLetterTopic})
+ go r.run()
+ }
+ return r, nil
+}
+
+func (r *dlqRouter) shouldSendToDlq(cm *ConsumerMessage) bool {
+ if r.policy == nil {
+ return false
+ }
+
+ msg := cm.Message.(*message)
+ r.log.WithField("count", msg.redeliveryCount).
+ WithField("max", r.policy.MaxDeliveries).
+ WithField("msgId", msg.msgID).
+ Debug("Should route to DLQ?")
+
+ // We use >= here because we're comparing the number of re-deliveries with
+ // the number of deliveries. So:
+ // * the user specifies that wants to process a message up to 10 times.
+ // * the first time, the redeliveryCount == 0, then 1 and so on
+ // * when we receive the message and redeliveryCount == 10, it means
+ // that the application has already got (and Nack()) the message 10
+ // times, so this time we should just go to DLQ.
+
+ return msg.redeliveryCount >= r.policy.MaxDeliveries
+}
+
+func (r *dlqRouter) Chan() chan ConsumerMessage {
+ return r.messageCh
+}
+
+func (r *dlqRouter) run() {
+ for {
+ select {
+ case cm := <-r.messageCh:
+ r.log.WithField("msgID", cm.ID()).Debug("Got message for DLQ")
+ producer := r.getProducer(cm.Consumer.(*consumer).options.Schema)
+ msg := cm.Message.(*message)
+ msgID := msg.ID()
+
+ // properties associated with original message
+ properties := msg.Properties()
+
+ // include orinal message id in string format in properties
+ properties[PropertyOriginMessageID] = msgID.String()
+
+ // include original topic name of the message in properties
+ properties[SysPropertyRealTopic] = msg.Topic()
+
+ producer.SendAsync(context.Background(), &ProducerMessage{
+ Payload: msg.Payload(),
+ Key: msg.Key(),
+ OrderingKey: msg.OrderingKey(),
+ Properties: properties,
+ EventTime: msg.EventTime(),
+ ReplicationClusters: msg.replicationClusters,
+ }, func(messageID MessageID, producerMessage *ProducerMessage, err error) {
+ if err == nil {
+ r.log.WithField("msgID", msgID).Debug("Succeed to send message to DLQ")
+ // The Producer ack might be coming from the connection go-routine that
+ // is also used by the consumer. In that case we would get a dead-lock
+ // if we'd try to ack.
+ go cm.Consumer.AckID(msgID)
+ } else {
+ r.log.WithError(err).WithField("msgID", msgID).Debug("Failed to send message to DLQ")
+ go cm.Consumer.Nack(cm)
+ }
+ })
+
+ case <-r.closeCh:
+ if r.producer != nil {
+ r.producer.Close()
+ }
+ r.log.Debug("Closed DLQ router")
+ return
+ }
+ }
+}
+
+func (r *dlqRouter) close() {
+ // Attempt to write on the close channel, without blocking
+ select {
+ case r.closeCh <- nil:
+ default:
+ }
+}
+
+func (r *dlqRouter) getProducer(schema Schema) Producer {
+ if r.producer != nil {
+ // Producer was already initialized
+ return r.producer
+ }
+
+ // Retry to create producer indefinitely
+ backoff := &internal.DefaultBackoff{}
+ for {
+ opt := r.policy.ProducerOptions
+ opt.Topic = r.policy.DeadLetterTopic
+ opt.Schema = schema
+
+ // the origin code sets to LZ4 compression with no options
+ // so the new design allows compression type to be overwritten but still set lz4 by default
+ if r.policy.ProducerOptions.CompressionType == NoCompression {
+ opt.CompressionType = LZ4
+ }
+ producer, err := r.client.CreateProducer(opt)
+
+ if err != nil {
+ r.log.WithError(err).Error("Failed to create DLQ producer")
+ time.Sleep(backoff.Next())
+ continue
+ } else {
+ r.producer = producer
+ return producer
+ }
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/encryption.go b/vendor/github.com/apache/pulsar-client-go/pulsar/encryption.go
new file mode 100644
index 00000000..3ab25278
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/encryption.go
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import "github.com/apache/pulsar-client-go/pulsar/crypto"
+
+// ProducerEncryptionInfo encryption related fields required by the producer
+type ProducerEncryptionInfo struct {
+ // KeyReader read RSA public/private key pairs
+ KeyReader crypto.KeyReader
+
+ // MessageCrypto used to encrypt and decrypt the data and session keys
+ MessageCrypto crypto.MessageCrypto
+
+ // Keys list of encryption key names to encrypt session key
+ Keys []string
+
+ // ProducerCryptoFailureAction action to be taken on failure of message encryption
+ // default is ProducerCryptoFailureActionFail
+ ProducerCryptoFailureAction int
+}
+
+// MessageDecryptionInfo encryption related fields required by the consumer to decrypt the message
+type MessageDecryptionInfo struct {
+ // KeyReader read RSA public/private key pairs
+ KeyReader crypto.KeyReader
+
+ // MessageCrypto used to encrypt and decrypt the data and session keys
+ MessageCrypto crypto.MessageCrypto
+
+ // ConsumerCryptoFailureAction action to be taken on failure of message decryption
+ ConsumerCryptoFailureAction int
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/error.go b/vendor/github.com/apache/pulsar-client-go/pulsar/error.go
new file mode 100644
index 00000000..73a0b606
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/error.go
@@ -0,0 +1,241 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "fmt"
+
+ proto "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+// Result used to represent pulsar processing is an alias of type int.
+type Result int
+
+const (
+ // Ok means no errors
+ Ok Result = iota
+ // UnknownError means unknown error happened on broker
+ UnknownError
+ // InvalidConfiguration means invalid configuration
+ InvalidConfiguration
+ // TimeoutError means operation timed out
+ TimeoutError
+ //LookupError means broker lookup failed
+ LookupError
+ // ConnectError means failed to connect to broker
+ ConnectError
+ // ReadError means failed to read from socket
+ ReadError
+ // AuthenticationError means authentication failed on broker
+ AuthenticationError
+ // AuthorizationError client is not authorized to create producer/consumer
+ AuthorizationError
+ // ErrorGettingAuthenticationData client cannot find authorization data
+ ErrorGettingAuthenticationData
+ // BrokerMetadataError broker failed in updating metadata
+ BrokerMetadataError
+ // BrokerPersistenceError broker failed to persist entry
+ BrokerPersistenceError
+ // ChecksumError corrupt message checksum failure
+ ChecksumError
+ // ConsumerBusy means Exclusive consumer is already connected
+ ConsumerBusy
+ // NotConnectedError producer/consumer is not currently connected to broker
+ NotConnectedError
+ // AlreadyClosedError producer/consumer is already closed and not accepting any operation
+ AlreadyClosedError
+ // InvalidMessage error in publishing an already used message
+ InvalidMessage
+ // ConsumerNotInitialized consumer is not initialized
+ ConsumerNotInitialized
+ // ProducerNotInitialized producer is not initialized
+ ProducerNotInitialized
+ // TooManyLookupRequestException too many concurrent LookupRequest
+ TooManyLookupRequestException
+ // InvalidTopicName means invalid topic name
+ InvalidTopicName
+ // InvalidURL means Client Initialized with Invalid Broker Url (VIP Url passed to Client Constructor)
+ InvalidURL
+ // ServiceUnitNotReady unloaded between client did lookup and producer/consumer got created
+ ServiceUnitNotReady
+ // OperationNotSupported operation not supported
+ OperationNotSupported
+ // ProducerBlockedQuotaExceededError producer is blocked
+ ProducerBlockedQuotaExceededError
+ // ProducerBlockedQuotaExceededException producer is getting exception
+ ProducerBlockedQuotaExceededException
+ // ProducerQueueIsFull producer queue is full
+ ProducerQueueIsFull
+ // MessageTooBig trying to send a messages exceeding the max size
+ MessageTooBig
+ // TopicNotFound topic not found
+ TopicNotFound
+ // SubscriptionNotFound subscription not found
+ SubscriptionNotFound
+ // ConsumerNotFound consumer not found
+ ConsumerNotFound
+ // UnsupportedVersionError when an older client/version doesn't support a required feature
+ UnsupportedVersionError
+ // TopicTerminated topic was already terminated
+ TopicTerminated
+ // CryptoError error when crypto operation fails
+ CryptoError
+ // ConsumerClosed means consumer already been closed
+ ConsumerClosed
+ // InvalidBatchBuilderType invalid batch builder type
+ InvalidBatchBuilderType
+ // AddToBatchFailed failed to add sendRequest to batchBuilder
+ AddToBatchFailed
+ // SeekFailed seek failed
+ SeekFailed
+ // ProducerClosed means producer already been closed
+ ProducerClosed
+ // SchemaFailure means the payload could not be encoded using the Schema
+ SchemaFailure
+ // InvalidStatus means the component status is not as expected.
+ InvalidStatus
+ // TransactionNoFoundError The transaction is not exist in the transaction coordinator, It may be an error txn
+ // or already ended.
+ TransactionNoFoundError
+ // ClientMemoryBufferIsFull client limit buffer is full
+ ClientMemoryBufferIsFull
+)
+
+// Error implement error interface, composed of two parts: msg and result.
+type Error struct {
+ msg string
+ result Result
+}
+
+// Result get error's original result.
+func (e *Error) Result() Result {
+ return e.result
+}
+
+func (e *Error) Error() string {
+ return e.msg
+}
+
+func newError(result Result, msg string) error {
+ return &Error{
+ msg: fmt.Sprintf("%s: %s", msg, getResultStr(result)),
+ result: result,
+ }
+}
+
+func getResultStr(r Result) string {
+ switch r {
+ case Ok:
+ return "OK"
+ case UnknownError:
+ return "UnknownError"
+ case InvalidConfiguration:
+ return "InvalidConfiguration"
+ case TimeoutError:
+ return "TimeoutError"
+ case LookupError:
+ return "LookupError"
+ case ConnectError:
+ return "ConnectError"
+ case ReadError:
+ return "ReadError"
+ case AuthenticationError:
+ return "AuthenticationError"
+ case AuthorizationError:
+ return "AuthorizationError"
+ case ErrorGettingAuthenticationData:
+ return "ErrorGettingAuthenticationData"
+ case BrokerMetadataError:
+ return "BrokerMetadataError"
+ case BrokerPersistenceError:
+ return "BrokerPersistenceError"
+ case ChecksumError:
+ return "ChecksumError"
+ case ConsumerBusy:
+ return "ConsumerBusy"
+ case NotConnectedError:
+ return "NotConnectedError"
+ case AlreadyClosedError:
+ return "AlreadyClosedError"
+ case InvalidMessage:
+ return "InvalidMessage"
+ case ConsumerNotInitialized:
+ return "ConsumerNotInitialized"
+ case ProducerNotInitialized:
+ return "ProducerNotInitialized"
+ case TooManyLookupRequestException:
+ return "TooManyLookupRequestException"
+ case InvalidTopicName:
+ return "InvalidTopicName"
+ case InvalidURL:
+ return "InvalidURL"
+ case ServiceUnitNotReady:
+ return "ServiceUnitNotReady"
+ case OperationNotSupported:
+ return "OperationNotSupported"
+ case ProducerBlockedQuotaExceededError:
+ return "ProducerBlockedQuotaExceededError"
+ case ProducerBlockedQuotaExceededException:
+ return "ProducerBlockedQuotaExceededException"
+ case ProducerQueueIsFull:
+ return "ProducerQueueIsFull"
+ case MessageTooBig:
+ return "MessageTooBig"
+ case TopicNotFound:
+ return "TopicNotFound"
+ case SubscriptionNotFound:
+ return "SubscriptionNotFound"
+ case ConsumerNotFound:
+ return "ConsumerNotFound"
+ case UnsupportedVersionError:
+ return "UnsupportedVersionError"
+ case TopicTerminated:
+ return "TopicTerminated"
+ case CryptoError:
+ return "CryptoError"
+ case ConsumerClosed:
+ return "ConsumerClosed"
+ case InvalidBatchBuilderType:
+ return "InvalidBatchBuilderType"
+ case AddToBatchFailed:
+ return "AddToBatchFailed"
+ case SeekFailed:
+ return "SeekFailed"
+ case ProducerClosed:
+ return "ProducerClosed"
+ case SchemaFailure:
+ return "SchemaFailure"
+ case ClientMemoryBufferIsFull:
+ return "ClientMemoryBufferIsFull"
+ case TransactionNoFoundError:
+ return "TransactionNoFoundError"
+ default:
+ return fmt.Sprintf("Result(%d)", r)
+ }
+}
+
+func getErrorFromServerError(serverError *proto.ServerError) error {
+ switch *serverError {
+ case proto.ServerError_TransactionNotFound:
+ return newError(TransactionNoFoundError, serverError.String())
+ case proto.ServerError_InvalidTxnStatus:
+ return newError(InvalidStatus, serverError.String())
+ default:
+ return newError(UnknownError, serverError.String())
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/helper.go b/vendor/github.com/apache/pulsar-client-go/pulsar/helper.go
new file mode 100644
index 00000000..5c68731f
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/helper.go
@@ -0,0 +1,79 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "fmt"
+
+ pkgerrors "github.com/pkg/errors"
+
+ "google.golang.org/protobuf/proto"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+// NewUnexpectedErrMsg instantiates an ErrUnexpectedMsg error.
+// Optionally provide a list of IDs associated with the message
+// for additional context in the error message.
+func newUnexpectedErrMsg(msgType pb.BaseCommand_Type, ids ...interface{}) *unexpectedErrMsg {
+ return &unexpectedErrMsg{
+ msgType: msgType,
+ ids: ids,
+ }
+}
+
+// UnexpectedErrMsg is returned when an unexpected message is received.
+type unexpectedErrMsg struct {
+ msgType pb.BaseCommand_Type
+ ids []interface{}
+}
+
+// Error satisfies the error interface.
+func (e *unexpectedErrMsg) Error() string {
+ msg := fmt.Sprintf("received unexpected message of type %q", e.msgType.String())
+ for _, id := range e.ids {
+ msg += fmt.Sprintf(" consumerID=%v", id)
+ }
+ return msg
+}
+
+func validateTopicNames(topics ...string) ([]*internal.TopicName, error) {
+ tns := make([]*internal.TopicName, len(topics))
+ for i, t := range topics {
+ tn, err := internal.ParseTopicName(t)
+ if err != nil {
+ return nil, pkgerrors.Wrapf(err, "invalid topic name: %s", t)
+ }
+ tns[i] = tn
+ }
+ return tns, nil
+}
+
+func toKeyValues(metadata map[string]string) []*pb.KeyValue {
+ kvs := make([]*pb.KeyValue, 0, len(metadata))
+ for k, v := range metadata {
+ kv := &pb.KeyValue{
+ Key: proto.String(k),
+ Value: proto.String(v),
+ }
+ kvs = append(kvs, kv)
+ }
+
+ return kvs
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/impl_message.go b/vendor/github.com/apache/pulsar-client-go/pulsar/impl_message.go
new file mode 100644
index 00000000..89a709f1
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/impl_message.go
@@ -0,0 +1,493 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "errors"
+ "fmt"
+ "math"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "google.golang.org/protobuf/proto"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/bits-and-blooms/bitset"
+)
+
+type messageID struct {
+ ledgerID int64
+ entryID int64
+ batchIdx int32
+ partitionIdx int32
+ batchSize int32
+}
+
+var latestMessageID = &messageID{
+ ledgerID: math.MaxInt64,
+ entryID: math.MaxInt64,
+ batchIdx: -1,
+ partitionIdx: -1,
+ batchSize: 0,
+}
+
+var earliestMessageID = &messageID{
+ ledgerID: -1,
+ entryID: -1,
+ batchIdx: -1,
+ partitionIdx: -1,
+ batchSize: 0,
+}
+
+type trackingMessageID struct {
+ *messageID
+
+ tracker *ackTracker
+ consumer acker
+ receivedTime time.Time
+}
+
+func (id *trackingMessageID) Ack() error {
+ if id.consumer == nil {
+ return errors.New("consumer is nil in trackingMessageID")
+ }
+ if id.ack() {
+ return id.consumer.AckID(id)
+ }
+
+ return nil
+}
+
+func (id *trackingMessageID) AckWithResponse() error {
+ if id.consumer == nil {
+ return errors.New("consumer is nil in trackingMessageID")
+ }
+ if id.ack() {
+ return id.consumer.AckIDWithResponse(id)
+ }
+
+ return nil
+}
+
+func (id *trackingMessageID) Nack() {
+ if id.consumer == nil {
+ return
+ }
+ id.consumer.NackID(id)
+}
+
+func (id *trackingMessageID) NackByMsg(msg Message) {
+ if id.consumer == nil {
+ return
+ }
+ id.consumer.NackMsg(msg)
+}
+
+func (id *trackingMessageID) ack() bool {
+ if id.tracker != nil && id.batchIdx > -1 {
+ return id.tracker.ack(int(id.batchIdx))
+ }
+ return true
+}
+
+func (id *trackingMessageID) ackCumulative() bool {
+ if id.tracker != nil && id.batchIdx > -1 {
+ return id.tracker.ackCumulative(int(id.batchIdx))
+ }
+ return true
+}
+
+func (id *trackingMessageID) prev() *trackingMessageID {
+ return &trackingMessageID{
+ messageID: &messageID{
+ ledgerID: id.ledgerID,
+ entryID: id.entryID - 1,
+ partitionIdx: id.partitionIdx,
+ },
+ tracker: id.tracker,
+ consumer: id.consumer,
+ }
+}
+
+func (id *messageID) isEntryIDValid() bool {
+ return id.entryID >= 0
+}
+
+func (id *messageID) greater(other *messageID) bool {
+ if id.ledgerID != other.ledgerID {
+ return id.ledgerID > other.ledgerID
+ }
+
+ if id.entryID != other.entryID {
+ return id.entryID > other.entryID
+ }
+
+ return id.batchIdx > other.batchIdx
+}
+
+func (id *messageID) equal(other *messageID) bool {
+ return id.ledgerID == other.ledgerID &&
+ id.entryID == other.entryID &&
+ id.batchIdx == other.batchIdx
+}
+
+func (id *messageID) greaterEqual(other *messageID) bool {
+ return id.equal(other) || id.greater(other)
+}
+
+func (id *messageID) Serialize() []byte {
+ msgID := &pb.MessageIdData{
+ LedgerId: proto.Uint64(uint64(id.ledgerID)),
+ EntryId: proto.Uint64(uint64(id.entryID)),
+ BatchIndex: proto.Int32(id.batchIdx),
+ Partition: proto.Int32(id.partitionIdx),
+ BatchSize: proto.Int32(id.batchSize),
+ }
+ data, _ := proto.Marshal(msgID)
+ return data
+}
+
+func (id *messageID) LedgerID() int64 {
+ return id.ledgerID
+}
+
+func (id *messageID) EntryID() int64 {
+ return id.entryID
+}
+
+func (id *messageID) BatchIdx() int32 {
+ return id.batchIdx
+}
+
+func (id *messageID) PartitionIdx() int32 {
+ return id.partitionIdx
+}
+
+func (id *messageID) BatchSize() int32 {
+ return id.batchSize
+}
+
+func (id *messageID) String() string {
+ return fmt.Sprintf("%d:%d:%d", id.ledgerID, id.entryID, id.partitionIdx)
+}
+
+func deserializeMessageID(data []byte) (MessageID, error) {
+ msgID := &pb.MessageIdData{}
+ err := proto.Unmarshal(data, msgID)
+ if err != nil {
+ return nil, err
+ }
+ id := newMessageID(
+ int64(msgID.GetLedgerId()),
+ int64(msgID.GetEntryId()),
+ msgID.GetBatchIndex(),
+ msgID.GetPartition(),
+ msgID.GetBatchSize(),
+ )
+ return id, nil
+}
+
+func newMessageID(ledgerID int64, entryID int64, batchIdx int32, partitionIdx int32, batchSize int32) MessageID {
+ return &messageID{
+ ledgerID: ledgerID,
+ entryID: entryID,
+ batchIdx: batchIdx,
+ partitionIdx: partitionIdx,
+ batchSize: batchSize,
+ }
+}
+
+func fromMessageID(msgID MessageID) *messageID {
+ return &messageID{
+ ledgerID: msgID.LedgerID(),
+ entryID: msgID.EntryID(),
+ batchIdx: msgID.BatchIdx(),
+ partitionIdx: msgID.PartitionIdx(),
+ batchSize: msgID.BatchSize(),
+ }
+}
+
+func newTrackingMessageID(ledgerID int64, entryID int64, batchIdx int32, partitionIdx int32, batchSize int32,
+ tracker *ackTracker) *trackingMessageID {
+ return &trackingMessageID{
+ messageID: &messageID{
+ ledgerID: ledgerID,
+ entryID: entryID,
+ batchIdx: batchIdx,
+ partitionIdx: partitionIdx,
+ batchSize: batchSize,
+ },
+ tracker: tracker,
+ receivedTime: time.Now(),
+ }
+}
+
+// checkMessageIDType checks if the MessageID is user-defined
+func checkMessageIDType(msgID MessageID) (valid bool) {
+ switch msgID.(type) {
+ case *trackingMessageID:
+ return true
+ case *chunkMessageID:
+ return true
+ case *messageID:
+ return true
+ default:
+ return false
+ }
+}
+
+func toTrackingMessageID(msgID MessageID) (trackingMsgID *trackingMessageID) {
+ if mid, ok := msgID.(*trackingMessageID); ok {
+ return mid
+ }
+ return &trackingMessageID{
+ messageID: fromMessageID(msgID),
+ }
+}
+
+func timeFromUnixTimestampMillis(timestamp uint64) time.Time {
+ ts := int64(timestamp) * int64(time.Millisecond)
+ seconds := ts / int64(time.Second)
+ nanos := ts - (seconds * int64(time.Second))
+ return time.Unix(seconds, nanos)
+}
+
+// EncryptionContext
+// It will be used to decrypt message outside of this client
+type EncryptionContext struct {
+ Keys map[string]EncryptionKey
+ Param []byte
+ Algorithm string
+ CompressionType CompressionType
+ UncompressedSize int
+ BatchSize int
+}
+
+// EncryptionKey
+// Encryption key used to encrypt the message payload
+type EncryptionKey struct {
+ KeyValue []byte
+ Metadata map[string]string
+}
+
+type message struct {
+ publishTime time.Time
+ eventTime time.Time
+ key string
+ orderingKey string
+ producerName string
+ payLoad []byte
+ msgID MessageID
+ properties map[string]string
+ topic string
+ replicationClusters []string
+ replicatedFrom string
+ redeliveryCount uint32
+ schema Schema
+ schemaVersion []byte
+ schemaInfoCache *schemaInfoCache
+ encryptionContext *EncryptionContext
+ index *uint64
+ brokerPublishTime *time.Time
+}
+
+func (msg *message) Topic() string {
+ return msg.topic
+}
+
+func (msg *message) Properties() map[string]string {
+ return msg.properties
+}
+
+func (msg *message) Payload() []byte {
+ return msg.payLoad
+}
+
+func (msg *message) ID() MessageID {
+ return msg.msgID
+}
+
+func (msg *message) PublishTime() time.Time {
+ return msg.publishTime
+}
+
+func (msg *message) EventTime() time.Time {
+ return msg.eventTime
+}
+
+func (msg *message) Key() string {
+ return msg.key
+}
+
+func (msg *message) OrderingKey() string {
+ return msg.orderingKey
+}
+
+func (msg *message) RedeliveryCount() uint32 {
+ return msg.redeliveryCount
+}
+
+func (msg *message) IsReplicated() bool {
+ return msg.replicatedFrom != ""
+}
+
+func (msg *message) GetReplicatedFrom() string {
+ return msg.replicatedFrom
+}
+
+func (msg *message) GetSchemaValue(v interface{}) error {
+ if msg.schemaVersion != nil {
+ schema, err := msg.schemaInfoCache.Get(msg.schemaVersion)
+ if err != nil {
+ return err
+ }
+ return schema.Decode(msg.payLoad, v)
+ }
+ return msg.schema.Decode(msg.payLoad, v)
+}
+
+func (msg *message) SchemaVersion() []byte {
+ return msg.schemaVersion
+}
+
+func (msg *message) ProducerName() string {
+ return msg.producerName
+}
+
+func (msg *message) GetEncryptionContext() *EncryptionContext {
+ return msg.encryptionContext
+}
+
+func (msg *message) Index() *uint64 {
+ return msg.index
+}
+
+func (msg *message) BrokerPublishTime() *time.Time {
+ return msg.brokerPublishTime
+}
+
+func (msg *message) size() int {
+ return len(msg.payLoad)
+}
+
+func newAckTracker(size uint) *ackTracker {
+ batchIDs := bitset.New(size)
+ for i := uint(0); i < size; i++ {
+ batchIDs.Set(i)
+ }
+ return &ackTracker{
+ size: size,
+ batchIDs: batchIDs,
+ }
+}
+
+type ackTracker struct {
+ sync.Mutex
+ size uint
+ batchIDs *bitset.BitSet
+ prevBatchAcked uint32
+}
+
+func (t *ackTracker) ack(batchID int) bool {
+ if batchID < 0 {
+ return true
+ }
+ t.Lock()
+ defer t.Unlock()
+ t.batchIDs.Clear(uint(batchID))
+ return t.batchIDs.None()
+}
+
+func (t *ackTracker) ackCumulative(batchID int) bool {
+ if batchID < 0 {
+ return true
+ }
+ t.Lock()
+ defer t.Unlock()
+ for i := 0; i <= batchID; i++ {
+ t.batchIDs.Clear(uint(i))
+ }
+ return t.batchIDs.None()
+}
+
+func (t *ackTracker) hasPrevBatchAcked() bool {
+ return atomic.LoadUint32(&t.prevBatchAcked) == 1
+}
+
+func (t *ackTracker) setPrevBatchAcked() {
+ atomic.StoreUint32(&t.prevBatchAcked, 1)
+}
+
+func (t *ackTracker) completed() bool {
+ t.Lock()
+ defer t.Unlock()
+ return t.batchIDs.None()
+}
+
+func (t *ackTracker) toAckSet() []int64 {
+ t.Lock()
+ defer t.Unlock()
+ if t.batchIDs.None() {
+ return nil
+ }
+ bytes := t.batchIDs.Bytes()
+ ackSet := make([]int64, len(bytes))
+ for i := 0; i < len(bytes); i++ {
+ ackSet[i] = int64(bytes[i])
+ }
+ return ackSet
+}
+
+type chunkMessageID struct {
+ *messageID
+
+ firstChunkID *messageID
+ receivedTime time.Time
+
+ consumer acker
+}
+
+func newChunkMessageID(firstChunkID *messageID, lastChunkID *messageID) *chunkMessageID {
+ return &chunkMessageID{
+ messageID: lastChunkID,
+ firstChunkID: firstChunkID,
+ receivedTime: time.Now(),
+ }
+}
+
+func (id chunkMessageID) String() string {
+ return fmt.Sprintf("%s;%s", id.firstChunkID.String(), id.messageID.String())
+}
+
+func (id chunkMessageID) Serialize() []byte {
+ msgID := &pb.MessageIdData{
+ LedgerId: proto.Uint64(uint64(id.ledgerID)),
+ EntryId: proto.Uint64(uint64(id.entryID)),
+ BatchIndex: proto.Int32(id.batchIdx),
+ Partition: proto.Int32(id.partitionIdx),
+ FirstChunkMessageId: &pb.MessageIdData{
+ LedgerId: proto.Uint64(uint64(id.firstChunkID.ledgerID)),
+ EntryId: proto.Uint64(uint64(id.firstChunkID.entryID)),
+ BatchIndex: proto.Int32(id.firstChunkID.batchIdx),
+ Partition: proto.Int32(id.firstChunkID.partitionIdx),
+ },
+ }
+ data, _ := proto.Marshal(msgID)
+ return data
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/backoff.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/backoff.go
new file mode 100644
index 00000000..3284fb7e
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/backoff.go
@@ -0,0 +1,63 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "math/rand"
+ "time"
+)
+
+func init() {
+ rand.Seed(time.Now().UnixNano())
+}
+
+// BackoffPolicy parameterize the following options in the reconnection logic to
+// allow users to customize the reconnection logic (minBackoff, maxBackoff and jitterPercentage)
+type BackoffPolicy interface {
+ Next() time.Duration
+}
+
+// DefaultBackoff computes the delay before retrying an action.
+// It uses an exponential backoff with jitter. The jitter represents up to 20 percents of the delay.
+type DefaultBackoff struct {
+ backoff time.Duration
+}
+
+const maxBackoff = 60 * time.Second
+
+// Next returns the delay to wait before next retry
+func (b *DefaultBackoff) Next() time.Duration {
+ minBackoff := 100 * time.Millisecond
+ jitterPercentage := 0.2
+
+ // Double the delay each time
+ b.backoff += b.backoff
+ if b.backoff.Nanoseconds() < minBackoff.Nanoseconds() {
+ b.backoff = minBackoff
+ } else if b.backoff.Nanoseconds() > maxBackoff.Nanoseconds() {
+ b.backoff = maxBackoff
+ }
+ jitter := rand.Float64() * float64(b.backoff) * jitterPercentage
+
+ return b.backoff + time.Duration(jitter)
+}
+
+// IsMaxBackoffReached evaluates if the max number of retries is reached
+func (b *DefaultBackoff) IsMaxBackoffReached() bool {
+ return b.backoff >= maxBackoff
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/batch_builder.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/batch_builder.go
new file mode 100644
index 00000000..649aba48
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/batch_builder.go
@@ -0,0 +1,310 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "bytes"
+ "time"
+
+ "google.golang.org/protobuf/proto"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal/compression"
+ "github.com/apache/pulsar-client-go/pulsar/internal/crypto"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+type BuffersPool interface {
+ GetBuffer() Buffer
+}
+
+// BatcherBuilderProvider defines func which returns the BatchBuilder.
+type BatcherBuilderProvider func(
+ maxMessages uint, maxBatchSize uint, maxMessageSize uint32, producerName string, producerID uint64,
+ compressionType pb.CompressionType, level compression.Level,
+ bufferPool BuffersPool, logger log.Logger, encryptor crypto.Encryptor,
+) (BatchBuilder, error)
+
+// BatchBuilder is a interface of batch builders
+type BatchBuilder interface {
+ // IsFull check if the size in the current batch exceeds the maximum size allowed by the batch
+ IsFull() bool
+
+ // Add will add single message to batch.
+ Add(
+ metadata *pb.SingleMessageMetadata, sequenceIDGenerator *uint64,
+ payload []byte,
+ callback interface{}, replicateTo []string, deliverAt time.Time,
+ schemaVersion []byte, multiSchemaEnabled bool,
+ ) bool
+
+ // Flush all the messages buffered in the client and wait until all messages have been successfully persisted.
+ Flush() (batchData Buffer, sequenceID uint64, callbacks []interface{}, err error)
+
+ // Flush all the messages buffered in multiple batches and wait until all
+ // messages have been successfully persisted.
+ FlushBatches() (
+ batchData []Buffer, sequenceID []uint64, callbacks [][]interface{}, errors []error,
+ )
+
+ // Return the batch container batch message in multiple batches.
+ IsMultiBatches() bool
+
+ reset()
+ Close() error
+}
+
+// batchContainer wraps the objects needed to a batch.
+// batchContainer implement BatchBuilder as a single batch container.
+type batchContainer struct {
+ buffer Buffer
+
+ // Current number of messages in the batch
+ numMessages uint
+
+ // Max number of message allowed in the batch
+ maxMessages uint
+
+ // The largest size for a batch sent from this particular producer.
+ // This is used as a baseline to allocate a new buffer that can hold the entire batch
+ // without needing costly re-allocations.
+ maxBatchSize uint
+
+ maxMessageSize uint32
+
+ producerName string
+ producerID uint64
+
+ cmdSend *pb.BaseCommand
+ msgMetadata *pb.MessageMetadata
+ callbacks []interface{}
+
+ compressionProvider compression.Provider
+ buffersPool BuffersPool
+
+ log log.Logger
+
+ encryptor crypto.Encryptor
+}
+
+// newBatchContainer init a batchContainer
+func newBatchContainer(
+ maxMessages uint, maxBatchSize uint, maxMessageSize uint32, producerName string, producerID uint64,
+ compressionType pb.CompressionType, level compression.Level,
+ bufferPool BuffersPool, logger log.Logger, encryptor crypto.Encryptor,
+) batchContainer {
+
+ bc := batchContainer{
+ buffer: NewBuffer(4096),
+ numMessages: 0,
+ maxMessages: maxMessages,
+ maxBatchSize: maxBatchSize,
+ maxMessageSize: maxMessageSize,
+ producerName: producerName,
+ producerID: producerID,
+ cmdSend: baseCommand(
+ pb.BaseCommand_SEND,
+ &pb.CommandSend{
+ ProducerId: &producerID,
+ },
+ ),
+ msgMetadata: &pb.MessageMetadata{
+ ProducerName: &producerName,
+ },
+ callbacks: []interface{}{},
+ compressionProvider: GetCompressionProvider(compressionType, level),
+ buffersPool: bufferPool,
+ log: logger,
+ encryptor: encryptor,
+ }
+
+ if compressionType != pb.CompressionType_NONE {
+ bc.msgMetadata.Compression = &compressionType
+ }
+
+ return bc
+}
+
+// NewBatchBuilder init batch builder and return BatchBuilder pointer. Build a new batch message container.
+func NewBatchBuilder(
+ maxMessages uint, maxBatchSize uint, maxMessageSize uint32, producerName string, producerID uint64,
+ compressionType pb.CompressionType, level compression.Level,
+ bufferPool BuffersPool, logger log.Logger, encryptor crypto.Encryptor,
+) (BatchBuilder, error) {
+
+ bc := newBatchContainer(
+ maxMessages, maxBatchSize, maxMessageSize, producerName, producerID, compressionType,
+ level, bufferPool, logger, encryptor,
+ )
+
+ return &bc, nil
+}
+
+// IsFull checks if the size in the current batch meets or exceeds the maximum size allowed by the batch
+func (bc *batchContainer) IsFull() bool {
+ return bc.numMessages >= bc.maxMessages || bc.buffer.ReadableBytes() >= uint32(bc.maxBatchSize)
+}
+
+// hasSpace should return true if and only if the batch container can accommodate another message of length payload.
+func (bc *batchContainer) hasSpace(payload []byte) bool {
+ if bc.numMessages == 0 {
+ // allow to add at least one message when batching is disabled
+ return true
+ }
+ msgSize := uint32(len(payload))
+ expectedSize := bc.buffer.ReadableBytes() + msgSize
+ return bc.numMessages+1 <= bc.maxMessages &&
+ expectedSize <= uint32(bc.maxBatchSize) && expectedSize <= bc.maxMessageSize
+}
+
+func (bc *batchContainer) hasSameSchema(schemaVersion []byte) bool {
+ if bc.numMessages == 0 {
+ return true
+ }
+ return bytes.Equal(bc.msgMetadata.SchemaVersion, schemaVersion)
+}
+
+// Add will add single message to batch.
+func (bc *batchContainer) Add(
+ metadata *pb.SingleMessageMetadata, sequenceIDGenerator *uint64,
+ payload []byte,
+ callback interface{}, replicateTo []string, deliverAt time.Time,
+ schemaVersion []byte, multiSchemaEnabled bool,
+) bool {
+
+ if replicateTo != nil && bc.numMessages != 0 {
+ // If the current batch is not empty and we're trying to set the replication clusters,
+ // then we need to force the current batch to flush and send the message individually
+ return false
+ } else if bc.msgMetadata.ReplicateTo != nil {
+ // There's already a message with cluster replication list. need to flush before next
+ // message can be sent
+ return false
+ } else if !bc.hasSpace(payload) {
+ // The current batch is full. Producer has to call Flush() to
+ return false
+ } else if multiSchemaEnabled && !bc.hasSameSchema(schemaVersion) {
+ // The current batch has a different schema. Producer has to call Flush() to
+ return false
+ }
+
+ if bc.numMessages == 0 {
+ var sequenceID uint64
+ if metadata.SequenceId != nil {
+ sequenceID = *metadata.SequenceId
+ } else {
+ sequenceID = GetAndAdd(sequenceIDGenerator, 1)
+ }
+ bc.msgMetadata.SequenceId = proto.Uint64(sequenceID)
+ bc.msgMetadata.PublishTime = proto.Uint64(TimestampMillis(time.Now()))
+ bc.msgMetadata.ProducerName = &bc.producerName
+ bc.msgMetadata.ReplicateTo = replicateTo
+ bc.msgMetadata.PartitionKey = metadata.PartitionKey
+ bc.msgMetadata.SchemaVersion = schemaVersion
+ bc.msgMetadata.Properties = metadata.Properties
+
+ if deliverAt.UnixNano() > 0 {
+ bc.msgMetadata.DeliverAtTime = proto.Int64(int64(TimestampMillis(deliverAt)))
+ }
+
+ bc.cmdSend.Send.SequenceId = proto.Uint64(sequenceID)
+ }
+ addSingleMessageToBatch(bc.buffer, metadata, payload)
+
+ bc.numMessages++
+ bc.callbacks = append(bc.callbacks, callback)
+ return true
+}
+
+func (bc *batchContainer) reset() {
+ bc.numMessages = 0
+ bc.buffer.Clear()
+ bc.callbacks = []interface{}{}
+ bc.msgMetadata.ReplicateTo = nil
+ bc.msgMetadata.DeliverAtTime = nil
+ bc.msgMetadata.SchemaVersion = nil
+ bc.msgMetadata.Properties = nil
+}
+
+// Flush all the messages buffered in the client and wait until all messages have been successfully persisted.
+func (bc *batchContainer) Flush() (
+ batchData Buffer, sequenceID uint64, callbacks []interface{}, err error,
+) {
+ if bc.numMessages == 0 {
+ // No-Op for empty batch
+ return nil, 0, nil, nil
+ }
+
+ bc.log.Debug("BatchBuilder flush: messages: ", bc.numMessages)
+
+ bc.msgMetadata.NumMessagesInBatch = proto.Int32(int32(bc.numMessages))
+ bc.cmdSend.Send.NumMessages = proto.Int32(int32(bc.numMessages))
+
+ uncompressedSize := bc.buffer.ReadableBytes()
+ bc.msgMetadata.UncompressedSize = &uncompressedSize
+
+ buffer := bc.buffersPool.GetBuffer()
+ if buffer == nil {
+ buffer = NewBuffer(int(uncompressedSize * 3 / 2))
+ }
+
+ if err = serializeMessage(
+ buffer, bc.cmdSend, bc.msgMetadata, bc.buffer, bc.compressionProvider,
+ bc.encryptor, bc.maxMessageSize, true,
+ ); err == nil { // no error in serializing Batch
+ sequenceID = bc.cmdSend.Send.GetSequenceId()
+ }
+
+ callbacks = bc.callbacks
+ bc.reset()
+ return buffer, sequenceID, callbacks, err
+}
+
+// FlushBatches only for multiple batches container
+func (bc *batchContainer) FlushBatches() (
+ batchData []Buffer, sequenceID []uint64, callbacks [][]interface{}, errors []error,
+) {
+ panic("single batch container not support FlushBatches(), please use Flush() instead")
+}
+
+// batchContainer as a single batch container
+func (bc *batchContainer) IsMultiBatches() bool {
+ return false
+}
+
+func (bc *batchContainer) Close() error {
+ return bc.compressionProvider.Close()
+}
+
+func GetCompressionProvider(
+ compressionType pb.CompressionType,
+ level compression.Level,
+) compression.Provider {
+ switch compressionType {
+ case pb.CompressionType_NONE:
+ return compression.NewNoopProvider()
+ case pb.CompressionType_LZ4:
+ return compression.NewLz4Provider()
+ case pb.CompressionType_ZLIB:
+ return compression.NewZLibProvider()
+ case pb.CompressionType_ZSTD:
+ return compression.NewZStdProvider(level)
+ default:
+ panic("unsupported compression type")
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/blocking_queue.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/blocking_queue.go
new file mode 100644
index 00000000..b44ec166
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/blocking_queue.go
@@ -0,0 +1,194 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "sync"
+)
+
+// BlockingQueue is a interface of block queue
+type BlockingQueue interface {
+ // Put enqueue one item, block if the queue is full
+ Put(item interface{})
+
+ // Take dequeue one item, block until it's available
+ Take() interface{}
+
+ // Poll dequeue one item, return nil if queue is empty
+ Poll() interface{}
+
+ // CompareAndPoll compare the first item and poll it if meet the conditions
+ CompareAndPoll(compare func(item interface{}) bool) interface{}
+
+ // Peek return the first item without dequeing, return nil if queue is empty
+ Peek() interface{}
+
+ // PeekLast return last item in queue without dequeing, return nil if queue is empty
+ PeekLast() interface{}
+
+ // Size return the current size of the queue
+ Size() int
+
+ // ReadableSlice returns a new view of the readable items in the queue
+ ReadableSlice() []interface{}
+}
+
+type blockingQueue struct {
+ items []interface{}
+ headIdx int
+ tailIdx int
+ size int
+ maxSize int
+
+ mutex sync.Mutex
+ isNotEmpty *sync.Cond
+ isNotFull *sync.Cond
+}
+
+// NewBlockingQueue init block queue and returns a BlockingQueue
+func NewBlockingQueue(maxSize int) BlockingQueue {
+ bq := &blockingQueue{
+ items: make([]interface{}, maxSize),
+ headIdx: 0,
+ tailIdx: 0,
+ size: 0,
+ maxSize: maxSize,
+ }
+
+ bq.isNotEmpty = sync.NewCond(&bq.mutex)
+ bq.isNotFull = sync.NewCond(&bq.mutex)
+ return bq
+}
+
+func (bq *blockingQueue) Put(item interface{}) {
+ bq.mutex.Lock()
+ defer bq.mutex.Unlock()
+
+ for bq.size == bq.maxSize {
+ bq.isNotFull.Wait()
+ }
+
+ wasEmpty := bq.size == 0
+
+ bq.items[bq.tailIdx] = item
+ bq.size++
+ bq.tailIdx++
+ if bq.tailIdx >= bq.maxSize {
+ bq.tailIdx = 0
+ }
+
+ if wasEmpty {
+ // Wake up eventual reader waiting for next item
+ bq.isNotEmpty.Signal()
+ }
+}
+
+func (bq *blockingQueue) Take() interface{} {
+ bq.mutex.Lock()
+ defer bq.mutex.Unlock()
+
+ for bq.size == 0 {
+ bq.isNotEmpty.Wait()
+ }
+
+ return bq.dequeue()
+}
+
+func (bq *blockingQueue) Poll() interface{} {
+ bq.mutex.Lock()
+ defer bq.mutex.Unlock()
+
+ if bq.size == 0 {
+ return nil
+ }
+
+ return bq.dequeue()
+}
+
+func (bq *blockingQueue) CompareAndPoll(compare func(interface{}) bool) interface{} {
+ bq.mutex.Lock()
+ defer bq.mutex.Unlock()
+
+ if bq.size == 0 {
+ return nil
+ }
+
+ if compare(bq.items[bq.headIdx]) {
+ return bq.dequeue()
+ }
+ return nil
+}
+
+func (bq *blockingQueue) Peek() interface{} {
+ bq.mutex.Lock()
+ defer bq.mutex.Unlock()
+
+ if bq.size == 0 {
+ return nil
+ }
+ return bq.items[bq.headIdx]
+}
+
+func (bq *blockingQueue) PeekLast() interface{} {
+ bq.mutex.Lock()
+ defer bq.mutex.Unlock()
+
+ if bq.size == 0 {
+ return nil
+ }
+ idx := (bq.headIdx + bq.size - 1) % bq.maxSize
+ return bq.items[idx]
+}
+
+func (bq *blockingQueue) dequeue() interface{} {
+ item := bq.items[bq.headIdx]
+ bq.items[bq.headIdx] = nil
+
+ bq.headIdx++
+ if bq.headIdx == len(bq.items) {
+ bq.headIdx = 0
+ }
+
+ bq.size--
+ bq.isNotFull.Signal()
+ return item
+}
+
+func (bq *blockingQueue) Size() int {
+ bq.mutex.Lock()
+ defer bq.mutex.Unlock()
+
+ return bq.size
+}
+
+func (bq *blockingQueue) ReadableSlice() []interface{} {
+ bq.mutex.Lock()
+ defer bq.mutex.Unlock()
+
+ res := make([]interface{}, bq.size)
+ readIdx := bq.headIdx
+ for i := 0; i < bq.size; i++ {
+ res[i] = bq.items[readIdx]
+ readIdx++
+ if readIdx == bq.maxSize {
+ readIdx = 0
+ }
+ }
+
+ return res
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/buffer.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/buffer.go
new file mode 100644
index 00000000..b3e23fbe
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/buffer.go
@@ -0,0 +1,219 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "encoding/binary"
+
+ log "github.com/sirupsen/logrus"
+)
+
+// Buffer is a variable-sized buffer of bytes with Read and Write methods.
+// The zero value for Buffer is an empty buffer ready to use.
+type Buffer interface {
+ ReadableBytes() uint32
+
+ WritableBytes() uint32
+
+ // Capacity returns the capacity of the buffer's underlying byte slice,
+ // that is, the total space allocated for the buffer's data.
+ Capacity() uint32
+
+ IsWritable() bool
+
+ Read(size uint32) []byte
+
+ Skip(size uint32)
+
+ Get(readerIndex uint32, size uint32) []byte
+
+ ReadableSlice() []byte
+
+ WritableSlice() []byte
+
+ // WrittenBytes advance the writer index when data was written in a slice
+ WrittenBytes(size uint32)
+
+ // MoveToFront copy the available portion of data at the beginning of the buffer
+ MoveToFront()
+
+ ReadUint16() uint16
+ ReadUint32() uint32
+
+ WriteUint16(n uint16)
+ WriteUint32(n uint32)
+
+ WriterIndex() uint32
+ ReaderIndex() uint32
+
+ Write(s []byte)
+
+ Put(writerIdx uint32, s []byte)
+ PutUint32(n uint32, writerIdx uint32)
+
+ Resize(newSize uint32)
+ ResizeIfNeeded(spaceNeeded uint32)
+
+ // Clear will clear the current buffer data.
+ Clear()
+}
+
+type buffer struct {
+ data []byte
+
+ readerIdx uint32
+ writerIdx uint32
+}
+
+// NewBuffer creates and initializes a new Buffer using buf as its initial contents.
+func NewBuffer(size int) Buffer {
+ return &buffer{
+ data: make([]byte, size),
+ readerIdx: 0,
+ writerIdx: 0,
+ }
+}
+
+func NewBufferWrapper(buf []byte) Buffer {
+ return &buffer{
+ data: buf,
+ readerIdx: 0,
+ writerIdx: uint32(len(buf)),
+ }
+}
+
+func (b *buffer) ReadableBytes() uint32 {
+ return b.writerIdx - b.readerIdx
+}
+
+func (b *buffer) WritableBytes() uint32 {
+ return uint32(cap(b.data)) - b.writerIdx
+}
+
+func (b *buffer) Capacity() uint32 {
+ return uint32(cap(b.data))
+}
+
+func (b *buffer) IsWritable() bool {
+ return b.WritableBytes() > 0
+}
+
+func (b *buffer) Read(size uint32) []byte {
+ // Check []byte slice size, avoid slice bounds out of range
+ if b.readerIdx+size > uint32(len(b.data)) {
+ log.Errorf("The input size [%d] > byte slice of data size [%d]", b.readerIdx+size, len(b.data))
+ return nil
+ }
+ res := b.data[b.readerIdx : b.readerIdx+size]
+ b.readerIdx += size
+ return res
+}
+
+func (b *buffer) Skip(size uint32) {
+ b.readerIdx += size
+}
+
+func (b *buffer) Get(readerIdx uint32, size uint32) []byte {
+ return b.data[readerIdx : readerIdx+size]
+}
+
+func (b *buffer) ReadableSlice() []byte {
+ return b.data[b.readerIdx:b.writerIdx]
+}
+
+func (b *buffer) WritableSlice() []byte {
+ return b.data[b.writerIdx:]
+}
+
+func (b *buffer) WrittenBytes(size uint32) {
+ b.writerIdx += size
+}
+
+func (b *buffer) WriterIndex() uint32 {
+ return b.writerIdx
+}
+
+func (b *buffer) ReaderIndex() uint32 {
+ return b.readerIdx
+}
+
+func (b *buffer) MoveToFront() {
+ size := b.ReadableBytes()
+ copy(b.data, b.Read(size))
+ b.readerIdx = 0
+ b.writerIdx = size
+}
+
+func (b *buffer) Resize(newSize uint32) {
+ newData := make([]byte, newSize)
+ size := b.ReadableBytes()
+ copy(newData, b.Read(size))
+ b.data = newData
+ b.readerIdx = 0
+ b.writerIdx = size
+}
+
+func (b *buffer) ResizeIfNeeded(spaceNeeded uint32) {
+ if b.WritableBytes() < spaceNeeded {
+ capacityNeeded := uint32(cap(b.data)) + spaceNeeded
+ minCapacityIncrease := uint32(cap(b.data) * 3 / 2)
+ if capacityNeeded < minCapacityIncrease {
+ capacityNeeded = minCapacityIncrease
+ }
+ b.Resize(capacityNeeded)
+ }
+}
+
+func (b *buffer) ReadUint32() uint32 {
+ return binary.BigEndian.Uint32(b.Read(4))
+}
+
+func (b *buffer) ReadUint16() uint16 {
+ return binary.BigEndian.Uint16(b.Read(2))
+}
+
+func (b *buffer) WriteUint32(n uint32) {
+ b.ResizeIfNeeded(4)
+ binary.BigEndian.PutUint32(b.WritableSlice(), n)
+ b.writerIdx += 4
+}
+
+func (b *buffer) PutUint32(n uint32, idx uint32) {
+ binary.BigEndian.PutUint32(b.data[idx:], n)
+}
+
+func (b *buffer) WriteUint16(n uint16) {
+ b.ResizeIfNeeded(2)
+ binary.BigEndian.PutUint16(b.WritableSlice(), n)
+ b.writerIdx += 2
+}
+
+func (b *buffer) Write(s []byte) {
+ b.ResizeIfNeeded(uint32(len(s)))
+ copy(b.WritableSlice(), s)
+ b.writerIdx += uint32(len(s))
+}
+
+func (b *buffer) Put(writerIdx uint32, s []byte) {
+ copy(b.data[writerIdx:], s)
+}
+
+func (b *buffer) Clear() {
+ b.readerIdx = 0
+ b.writerIdx = 0
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/channel_cond.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/channel_cond.go
new file mode 100644
index 00000000..38301abe
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/channel_cond.go
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "context"
+ "sync"
+ "sync/atomic"
+ "unsafe"
+)
+
+type chCond struct {
+ L sync.Locker
+ // The pointer to the channel, the channel pointed to may change,
+ // because we will use the channel's close mechanism to implement broadcast notifications.
+ notifyChPtr unsafe.Pointer
+}
+
+func newCond(l sync.Locker) *chCond {
+ c := &chCond{L: l}
+ n := make(chan struct{})
+ c.notifyChPtr = unsafe.Pointer(&n)
+ return c
+}
+
+// wait for broadcast calls. Similar to regular sync.Cond
+func (c *chCond) wait() {
+ n := c.notifyChan()
+ c.L.Unlock()
+ <-n
+ c.L.Lock()
+}
+
+// waitWithContext Same as wait() call, but the end condition can also be controlled through the context.
+func (c *chCond) waitWithContext(ctx context.Context) bool {
+ n := c.notifyChan()
+ c.L.Unlock()
+ defer c.L.Lock()
+ select {
+ case <-n:
+ return true
+ case <-ctx.Done():
+ return false
+ default:
+ return true
+ }
+}
+
+// broadcast wakes all goroutines waiting on c.
+// It is not required for the caller to hold c.L during the call.
+func (c *chCond) broadcast() {
+ n := make(chan struct{})
+ ptrOld := atomic.SwapPointer(&c.notifyChPtr, unsafe.Pointer(&n))
+ // close old channels to trigger broadcast.
+ close(*(*chan struct{})(ptrOld))
+}
+
+func (c *chCond) notifyChan() <-chan struct{} {
+ ptr := atomic.LoadPointer(&c.notifyChPtr)
+ return *((*chan struct{})(ptr))
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/checksum.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/checksum.go
new file mode 100644
index 00000000..e7cf7874
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/checksum.go
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "hash"
+ "hash/crc32"
+)
+
+// crc32cTable holds the precomputed crc32 hash table
+// used by Pulsar (crc32c)
+var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
+
+type CheckSum struct {
+ hash hash.Hash
+}
+
+// Crc32cCheckSum handles computing the checksum.
+func Crc32cCheckSum(data []byte) uint32 {
+ return crc32.Checksum(data, crc32cTable)
+}
+
+func (cs *CheckSum) Write(p []byte) (int, error) {
+ if cs.hash == nil {
+ cs.hash = crc32.New(crc32cTable)
+ }
+ return cs.hash.Write(p)
+}
+
+func (cs *CheckSum) compute() []byte {
+ if cs.hash == nil {
+ return nil
+ }
+ return cs.hash.Sum(nil)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/client_handlers.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/client_handlers.go
new file mode 100644
index 00000000..39b9bb78
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/client_handlers.go
@@ -0,0 +1,63 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import "sync"
+
+// ClientHandlerMap is a simple concurrent-safe map for the client type
+type ClientHandlers struct {
+ handlers map[Closable]bool
+ l *sync.RWMutex
+}
+
+func NewClientHandlers() ClientHandlers {
+ return ClientHandlers{
+ handlers: map[Closable]bool{},
+ l: &sync.RWMutex{},
+ }
+}
+func (h *ClientHandlers) Add(c Closable) {
+ h.l.Lock()
+ defer h.l.Unlock()
+ h.handlers[c] = true
+}
+
+func (h *ClientHandlers) Del(c Closable) {
+ h.l.Lock()
+ defer h.l.Unlock()
+ delete(h.handlers, c)
+}
+
+func (h *ClientHandlers) Val(c Closable) bool {
+ h.l.RLock()
+ defer h.l.RUnlock()
+ return h.handlers[c]
+}
+
+func (h *ClientHandlers) Close() {
+ h.l.Lock()
+ handlers := make([]Closable, 0, len(h.handlers))
+ for handler := range h.handlers {
+ handlers = append(handlers, handler)
+ }
+ h.l.Unlock()
+
+ for _, handler := range handlers {
+ handler.Close()
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/closable.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/closable.go
new file mode 100644
index 00000000..ac26e1ea
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/closable.go
@@ -0,0 +1,22 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+type Closable interface {
+ Close()
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/commands.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/commands.go
new file mode 100644
index 00000000..00e075be
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/commands.go
@@ -0,0 +1,378 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+
+ "google.golang.org/protobuf/proto"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal/compression"
+ "github.com/apache/pulsar-client-go/pulsar/internal/crypto"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+const (
+ // MaxMessageSize limit message size for transfer
+ MaxMessageSize = 5 * 1024 * 1024
+ // MessageFramePadding is for metadata and other frame headers
+ MessageFramePadding = 10 * 1024
+ // MaxFrameSize limit the maximum size that pulsar allows for messages to be sent.
+ MaxFrameSize = MaxMessageSize + MessageFramePadding
+ magicCrc32c uint16 = 0x0e01
+ magicBrokerEntryMetadata uint16 = 0x0e02
+)
+
+// ErrCorruptedMessage is the error returned by ReadMessageData when it has detected corrupted data.
+// The data is considered corrupted if it's missing a header, a checksum mismatch or there
+// was an error when unmarshalling the message metadata.
+var ErrCorruptedMessage = errors.New("corrupted message")
+
+// ErrEOM is the error returned by ReadMessage when no more input is available.
+var ErrEOM = errors.New("EOF")
+
+var ErrConnectionClosed = errors.New("connection closed")
+
+var ErrExceedMaxMessageSize = errors.New("encryptedPayload exceeds MaxMessageSize")
+
+func NewMessageReader(headersAndPayload Buffer) *MessageReader {
+ return &MessageReader{
+ buffer: headersAndPayload,
+ }
+}
+
+func NewMessageReaderFromArray(headersAndPayload []byte) *MessageReader {
+ return NewMessageReader(NewBufferWrapper(headersAndPayload))
+}
+
+// MessageReader provides helper methods to parse
+// the metadata and messages from the binary format
+// Wire format for a messages
+//
+// Old format (single message)
+// [MAGIC_NUMBER][CHECKSUM] [METADATA_SIZE][METADATA] [PAYLOAD]
+//
+// Batch format
+// [MAGIC_NUMBER][CHECKSUM] [METADATA_SIZE][METADATA] [METADATA_SIZE][METADATA][PAYLOAD]
+// [METADATA_SIZE][METADATA][PAYLOAD]
+type MessageReader struct {
+ buffer Buffer
+ // true if we are parsing a batched message - set after parsing the message metadata
+ batched bool
+}
+
+// ReadChecksum
+func (r *MessageReader) readChecksum() (uint32, error) {
+ if r.buffer.ReadableBytes() < 6 {
+ return 0, errors.New("missing message header")
+ }
+ // reader magic number
+ magicNumber := r.buffer.ReadUint16()
+ if magicNumber != magicCrc32c {
+ return 0, ErrCorruptedMessage
+ }
+ checksum := r.buffer.ReadUint32()
+ return checksum, nil
+}
+
+func (r *MessageReader) ReadMessageMetadata() (*pb.MessageMetadata, error) {
+ // Wire format
+ // [MAGIC_NUMBER][CHECKSUM] [METADATA_SIZE][METADATA]
+
+ // read checksum
+ checksum, err := r.readChecksum()
+ if err != nil {
+ return nil, err
+ }
+
+ // validate checksum
+ computedChecksum := Crc32cCheckSum(r.buffer.ReadableSlice())
+ if checksum != computedChecksum {
+ return nil, fmt.Errorf("checksum mismatch received: 0x%x computed: 0x%x", checksum, computedChecksum)
+ }
+
+ size := r.buffer.ReadUint32()
+ data := r.buffer.Read(size)
+ var meta pb.MessageMetadata
+ if err := proto.Unmarshal(data, &meta); err != nil {
+ return nil, ErrCorruptedMessage
+ }
+
+ if meta.NumMessagesInBatch != nil {
+ r.batched = true
+ }
+
+ return &meta, nil
+}
+
+func (r *MessageReader) ReadBrokerMetadata() (*pb.BrokerEntryMetadata, error) {
+ magicNumber := binary.BigEndian.Uint16(r.buffer.Get(r.buffer.ReaderIndex(), 2))
+ if magicNumber != magicBrokerEntryMetadata {
+ return nil, nil
+ }
+ r.buffer.Skip(2)
+ size := r.buffer.ReadUint32()
+ var brokerEntryMetadata pb.BrokerEntryMetadata
+ if err := proto.Unmarshal(r.buffer.Read(size), &brokerEntryMetadata); err != nil {
+ return nil, err
+ }
+ return &brokerEntryMetadata, nil
+}
+
+func (r *MessageReader) ReadMessage() (*pb.SingleMessageMetadata, []byte, error) {
+ if r.buffer.ReadableBytes() == 0 && r.buffer.Capacity() > 0 {
+ return nil, nil, ErrEOM
+ }
+ if !r.batched {
+ return r.readMessage()
+ }
+
+ return r.readSingleMessage()
+}
+
+func (r *MessageReader) readMessage() (*pb.SingleMessageMetadata, []byte, error) {
+ // Wire format
+ // [PAYLOAD]
+
+ return nil, r.buffer.Read(r.buffer.ReadableBytes()), nil
+}
+
+func (r *MessageReader) readSingleMessage() (*pb.SingleMessageMetadata, []byte, error) {
+ // Wire format
+ // [METADATA_SIZE][METADATA][PAYLOAD]
+
+ size := r.buffer.ReadUint32()
+ var meta pb.SingleMessageMetadata
+ if err := proto.Unmarshal(r.buffer.Read(size), &meta); err != nil {
+ return nil, nil, err
+ }
+
+ return &meta, r.buffer.Read(uint32(meta.GetPayloadSize())), nil
+}
+
+func (r *MessageReader) ResetBuffer(buffer Buffer) {
+ r.buffer = buffer
+}
+
+func baseCommand(cmdType pb.BaseCommand_Type, msg proto.Message) *pb.BaseCommand {
+ cmd := &pb.BaseCommand{
+ Type: &cmdType,
+ }
+ switch cmdType {
+ case pb.BaseCommand_CONNECT:
+ cmd.Connect = msg.(*pb.CommandConnect)
+ case pb.BaseCommand_LOOKUP:
+ cmd.LookupTopic = msg.(*pb.CommandLookupTopic)
+ case pb.BaseCommand_PARTITIONED_METADATA:
+ cmd.PartitionMetadata = msg.(*pb.CommandPartitionedTopicMetadata)
+ case pb.BaseCommand_PRODUCER:
+ cmd.Producer = msg.(*pb.CommandProducer)
+ case pb.BaseCommand_SUBSCRIBE:
+ cmd.Subscribe = msg.(*pb.CommandSubscribe)
+ case pb.BaseCommand_FLOW:
+ cmd.Flow = msg.(*pb.CommandFlow)
+ case pb.BaseCommand_PING:
+ cmd.Ping = msg.(*pb.CommandPing)
+ case pb.BaseCommand_PONG:
+ cmd.Pong = msg.(*pb.CommandPong)
+ case pb.BaseCommand_SEND:
+ cmd.Send = msg.(*pb.CommandSend)
+ case pb.BaseCommand_SEND_ERROR:
+ cmd.SendError = msg.(*pb.CommandSendError)
+ case pb.BaseCommand_CLOSE_PRODUCER:
+ cmd.CloseProducer = msg.(*pb.CommandCloseProducer)
+ case pb.BaseCommand_CLOSE_CONSUMER:
+ cmd.CloseConsumer = msg.(*pb.CommandCloseConsumer)
+ case pb.BaseCommand_ACK:
+ cmd.Ack = msg.(*pb.CommandAck)
+ case pb.BaseCommand_SEEK:
+ cmd.Seek = msg.(*pb.CommandSeek)
+ case pb.BaseCommand_UNSUBSCRIBE:
+ cmd.Unsubscribe = msg.(*pb.CommandUnsubscribe)
+ case pb.BaseCommand_REDELIVER_UNACKNOWLEDGED_MESSAGES:
+ cmd.RedeliverUnacknowledgedMessages = msg.(*pb.CommandRedeliverUnacknowledgedMessages)
+ case pb.BaseCommand_GET_TOPICS_OF_NAMESPACE:
+ cmd.GetTopicsOfNamespace = msg.(*pb.CommandGetTopicsOfNamespace)
+ case pb.BaseCommand_GET_LAST_MESSAGE_ID:
+ cmd.GetLastMessageId = msg.(*pb.CommandGetLastMessageId)
+ case pb.BaseCommand_AUTH_RESPONSE:
+ cmd.AuthResponse = msg.(*pb.CommandAuthResponse)
+ case pb.BaseCommand_GET_OR_CREATE_SCHEMA:
+ cmd.GetOrCreateSchema = msg.(*pb.CommandGetOrCreateSchema)
+ case pb.BaseCommand_GET_SCHEMA:
+ cmd.GetSchema = msg.(*pb.CommandGetSchema)
+ case pb.BaseCommand_TC_CLIENT_CONNECT_REQUEST:
+ cmd.TcClientConnectRequest = msg.(*pb.CommandTcClientConnectRequest)
+ case pb.BaseCommand_NEW_TXN:
+ cmd.NewTxn = msg.(*pb.CommandNewTxn)
+ case pb.BaseCommand_ADD_PARTITION_TO_TXN:
+ cmd.AddPartitionToTxn = msg.(*pb.CommandAddPartitionToTxn)
+ case pb.BaseCommand_ADD_SUBSCRIPTION_TO_TXN:
+ cmd.AddSubscriptionToTxn = msg.(*pb.CommandAddSubscriptionToTxn)
+ case pb.BaseCommand_END_TXN:
+ cmd.EndTxn = msg.(*pb.CommandEndTxn)
+
+ default:
+ panic(fmt.Sprintf("Missing command type: %v", cmdType))
+ }
+
+ return cmd
+}
+
+func addSingleMessageToBatch(wb Buffer, smm *pb.SingleMessageMetadata, payload []byte) {
+ metadataSize := uint32(proto.Size(smm))
+ wb.WriteUint32(metadataSize)
+
+ wb.ResizeIfNeeded(metadataSize)
+ err := MarshalToSizedBuffer(smm, wb.WritableSlice()[:metadataSize])
+ if err != nil {
+ panic(fmt.Sprintf("Protobuf serialization error: %v", err))
+ }
+
+ wb.WrittenBytes(metadataSize)
+ wb.Write(payload)
+}
+
+func serializeMessage(wb Buffer,
+ cmdSend *pb.BaseCommand,
+ msgMetadata *pb.MessageMetadata,
+ payload Buffer,
+ compressionProvider compression.Provider,
+ encryptor crypto.Encryptor,
+ maxMessageSize uint32,
+ doCompress bool) error {
+ // Wire format
+ // [TOTAL_SIZE] [CMD_SIZE][CMD] [MAGIC_NUMBER][CHECKSUM] [METADATA_SIZE][METADATA] [PAYLOAD]
+
+ // compress the payload
+ var compressedPayload []byte
+ if doCompress {
+ compressedPayload = compressionProvider.Compress(nil, payload.ReadableSlice())
+ } else {
+ compressedPayload = payload.ReadableSlice()
+ }
+
+ // encrypt the compressed payload
+ encryptedPayload, err := encryptor.Encrypt(compressedPayload, msgMetadata)
+ if err != nil {
+ // error occurred while encrypting the payload, ProducerCryptoFailureAction is set to Fail
+ return fmt.Errorf("encryption of message failed, ProducerCryptoFailureAction is set to Fail. Error :%v", err)
+ }
+
+ cmdSize := uint32(proto.Size(cmdSend))
+ msgMetadataSize := uint32(proto.Size(msgMetadata))
+ msgSize := len(encryptedPayload) + int(msgMetadataSize)
+
+ // the maxMessageSize check of batching message is in here
+ if !(msgMetadata.GetTotalChunkMsgSize() != 0) && msgSize > int(maxMessageSize) {
+ return fmt.Errorf("%w, size: %d, MaxMessageSize: %d",
+ ErrExceedMaxMessageSize, msgSize, maxMessageSize)
+ }
+
+ frameSizeIdx := wb.WriterIndex()
+ wb.WriteUint32(0) // Skip frame size until we now the size
+ frameStartIdx := wb.WriterIndex()
+
+ // Write cmd
+ wb.WriteUint32(cmdSize)
+ wb.ResizeIfNeeded(cmdSize)
+ err = MarshalToSizedBuffer(cmdSend, wb.WritableSlice()[:cmdSize])
+ if err != nil {
+ panic(fmt.Sprintf("Protobuf error when serializing cmdSend: %v", err))
+ }
+ wb.WrittenBytes(cmdSize)
+
+ // Create checksum placeholder
+ wb.WriteUint16(magicCrc32c)
+ checksumIdx := wb.WriterIndex()
+ wb.WriteUint32(0) // skip 4 bytes of checksum
+
+ // Write metadata
+ metadataStartIdx := wb.WriterIndex()
+ wb.WriteUint32(msgMetadataSize)
+ wb.ResizeIfNeeded(msgMetadataSize)
+ err = MarshalToSizedBuffer(msgMetadata, wb.WritableSlice()[:msgMetadataSize])
+ if err != nil {
+ panic(fmt.Sprintf("Protobuf error when serializing msgMetadata: %v", err))
+ }
+ wb.WrittenBytes(msgMetadataSize)
+
+ // add payload to the buffer
+ wb.Write(encryptedPayload)
+
+ // Write checksum at created checksum-placeholder
+ frameEndIdx := wb.WriterIndex()
+ checksum := Crc32cCheckSum(wb.Get(metadataStartIdx, frameEndIdx-metadataStartIdx))
+
+ // Set Sizes and checksum in the fixed-size header
+ wb.PutUint32(frameEndIdx-frameStartIdx, frameSizeIdx) // External frame
+ wb.PutUint32(checksum, checksumIdx)
+ return nil
+}
+
+func SingleSend(wb Buffer,
+ producerID, sequenceID uint64,
+ msgMetadata *pb.MessageMetadata,
+ compressedPayload Buffer,
+ encryptor crypto.Encryptor,
+ maxMassageSize uint32) error {
+ cmdSend := baseCommand(
+ pb.BaseCommand_SEND,
+ &pb.CommandSend{
+ ProducerId: &producerID,
+ },
+ )
+ cmdSend.Send.SequenceId = &sequenceID
+ if msgMetadata.GetTotalChunkMsgSize() > 1 {
+ isChunk := true
+ cmdSend.Send.IsChunk = &isChunk
+ }
+ // payload has been compressed so compressionProvider can be nil
+ return serializeMessage(wb, cmdSend, msgMetadata, compressedPayload,
+ nil, encryptor, maxMassageSize, false)
+}
+
+// ConvertFromStringMap convert a string map to a KeyValue []byte
+func ConvertFromStringMap(m map[string]string) []*pb.KeyValue {
+ list := make([]*pb.KeyValue, len(m))
+
+ i := 0
+ for k, v := range m {
+ list[i] = &pb.KeyValue{
+ Key: proto.String(k),
+ Value: proto.String(v),
+ }
+
+ i++
+ }
+
+ return list
+}
+
+// ConvertToStringMap convert a KeyValue []byte to string map
+func ConvertToStringMap(pbb []*pb.KeyValue) map[string]string {
+ m := make(map[string]string)
+
+ for _, kv := range pbb {
+ m[*kv.Key] = *kv.Value
+ }
+
+ return m
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/compression.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/compression.go
new file mode 100644
index 00000000..a4504bf1
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/compression.go
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package compression
+
+import "io"
+
+type Level int
+
+const (
+ Default Level = iota
+ Faster
+ Better
+)
+
+// Provider is a interface of compression providers
+type Provider interface {
+ // Return the max possible size for a compressed buffer given the uncompressed data size
+ CompressMaxSize(originalSize int) int
+
+ // Compress a []byte, the param is a []byte with the uncompressed content.
+ // The reader/writer indexes will not be modified. The return is a []byte
+ // with the compressed content.
+ Compress(dst, src []byte) []byte
+
+ // Decompress a []byte. The buffer needs to have been compressed with the matching Encoder.
+ // The src is compressed content. If dst is passed, the decompressed data will be written there
+ // The return were the result will be passed, if err is nil, the buffer was decompressed, no nil otherwise.
+ Decompress(dst, src []byte, originalSize int) ([]byte, error)
+
+ // Returns a new instance of the same provider, with the same exact configuration
+ Clone() Provider
+
+ // Close the compressor
+ io.Closer
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/lz4.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/lz4.go
new file mode 100644
index 00000000..745ea831
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/lz4.go
@@ -0,0 +1,105 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package compression
+
+import (
+ "github.com/pierrec/lz4"
+)
+
+const (
+ minLz4DestinationBufferSize = 1024 * 1024
+)
+
+type lz4Provider struct {
+ hashTable []int
+}
+
+// NewLz4Provider return a interface of Provider.
+func NewLz4Provider() Provider {
+ const tableSize = 1 << 16
+
+ return &lz4Provider{
+ hashTable: make([]int, tableSize),
+ }
+}
+
+func (l *lz4Provider) CompressMaxSize(originalSize int) int {
+ s := lz4.CompressBlockBound(originalSize)
+ if s < minLz4DestinationBufferSize {
+ return minLz4DestinationBufferSize
+ }
+
+ return s
+}
+
+func (l *lz4Provider) Compress(dst, data []byte) []byte {
+ maxSize := lz4.CompressBlockBound(len(data))
+ if cap(dst) >= maxSize {
+ dst = dst[0:maxSize] // Reuse dst buffer
+ } else {
+ dst = make([]byte, maxSize)
+ }
+ size, err := lz4.CompressBlock(data, dst, l.hashTable)
+ if err != nil {
+ panic("Failed to compress")
+ }
+
+ if size == 0 {
+ // The data block was not compressed. Just repeat it with
+ // the block header flag to signal it's not compressed
+ headerSize := writeSize(len(data), dst)
+ copy(dst[headerSize:], data)
+ return dst[:len(data)+headerSize]
+ }
+ return dst[:size]
+}
+
+// Write the encoded size for the uncompressed payload
+func writeSize(size int, dst []byte) int {
+ if size < 0xF {
+ dst[0] |= byte(size << 4)
+ return 1
+ }
+ dst[0] |= 0xF0
+ l := size - 0xF
+ i := 1
+ for ; l >= 0xFF; l -= 0xFF {
+ dst[i] = 0xFF
+ i++
+ }
+ dst[i] = byte(l)
+ return i + 1
+}
+
+func (lz4Provider) Decompress(dst, src []byte, originalSize int) ([]byte, error) {
+ if cap(dst) >= originalSize {
+ dst = dst[0:originalSize] // Reuse dst buffer
+ } else {
+ dst = make([]byte, originalSize)
+ }
+ _, err := lz4.UncompressBlock(src, dst)
+ return dst, err
+}
+
+func (lz4Provider) Close() error {
+ return nil
+}
+
+func (lz4Provider) Clone() Provider {
+ return NewLz4Provider()
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/noop.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/noop.go
new file mode 100644
index 00000000..78acb52d
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/noop.go
@@ -0,0 +1,61 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package compression
+
+import (
+ "bytes"
+)
+
+type noopProvider struct{}
+
+// NewNoopProvider returns a Provider interface that does not compress the data
+func NewNoopProvider() Provider {
+ return &noopProvider{}
+}
+
+func (noopProvider) CompressMaxSize(originalSize int) int {
+ return originalSize
+}
+
+func (noopProvider) Compress(dst, src []byte) []byte {
+ if dst == nil {
+ dst = make([]byte, len(src))
+ }
+
+ b := bytes.NewBuffer(dst[:0])
+ b.Write(src)
+ return dst[:len(src)]
+}
+
+func (noopProvider) Decompress(dst, src []byte, originalSize int) ([]byte, error) {
+ if dst == nil {
+ dst = make([]byte, len(src))
+ }
+
+ b := bytes.NewBuffer(dst[:0])
+ b.Write(src)
+ return dst[:len(src)], nil
+}
+
+func (noopProvider) Close() error {
+ return nil
+}
+
+func (noopProvider) Clone() Provider {
+ return NewNoopProvider()
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/test_data_sample.txt b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/test_data_sample.txt
new file mode 100644
index 00000000..89e3e478
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/test_data_sample.txt
@@ -0,0 +1,1795 @@
+**The Project Gutenberg Etext of A Child's History of England**
+#11 in our series by Charles Dickens
+
+
+Copyright laws are changing all over the world, be sure to check
+the copyright laws for your country before posting these files!!
+
+Please take a look at the important information in this header.
+We encourage you to keep this file on your own disk, keeping an
+electronic path open for the next readers. Do not remove this.
+
+
+**Welcome To The World of Free Plain Vanilla Electronic Texts**
+
+**Etexts Readable By Both Humans and By Computers, Since 1971**
+
+*These Etexts Prepared By Hundreds of Volunteers and Donations*
+
+Information on contacting Project Gutenberg to get Etexts, and
+further information is included below. We need your donations.
+
+
+A Child's History of England
+
+by Charles Dickens
+
+October, 1996 [Etext #699]
+
+
+**The Project Gutenberg Etext of A Child's History of England**
+*****This file should be named achoe10.txt or achoe10.zip******
+
+Corrected EDITIONS of our etexts get a new NUMBER, achoe11.txt.
+VERSIONS based on separate sources get new LETTER, achoe10a.txt.
+
+
+We are now trying to release all our books one month in advance
+of the official release dates, for time for better editing.
+
+Please note: neither this list nor its contents are final till
+midnight of the last day of the month of any such announcement.
+The official release date of all Project Gutenberg Etexts is at
+Midnight, Central Time, of the last day of the stated month. A
+preliminary version may often be posted for suggestion, comment
+and editing by those who wish to do so. To be sure you have an
+up to date first edition [xxxxx10x.xxx] please check file sizes
+in the first week of the next month. Since our ftp program has
+a bug in it that scrambles the date [tried to fix and failed] a
+look at the file size will have to do, but we will try to see a
+new copy has at least one byte more or less.
+
+
+Information about Project Gutenberg (one page)
+
+We produce about two million dollars for each hour we work. The
+fifty hours is one conservative estimate for how long it we take
+to get any etext selected, entered, proofread, edited, copyright
+searched and analyzed, the copyright letters written, etc. This
+projected audience is one hundred million readers. If our value
+per text is nominally estimated at one dollar then we produce $2
+million dollars per hour this year as we release thirty-two text
+files per month: or 400 more Etexts in 1996 for a total of 800.
+If these reach just 10% of the computerized population, then the
+total should reach 80 billion Etexts.
+
+The Goal of Project Gutenberg is to Give Away One Trillion Etext
+Files by the December 31, 2001. [10,000 x 100,000,000=Trillion]
+This is ten thousand titles each to one hundred million readers,
+which is only 10% of the present number of computer users. 2001
+should have at least twice as many computer users as that, so it
+will require us reaching less than 5% of the users in 2001.
+
+
+We need your donations more than ever!
+
+
+All donations should be made to "Project Gutenberg/BU": and are
+tax deductible to the extent allowable by law. (BU = Benedictine
+University). (Subscriptions to our paper newsletter go to BU.)
+
+For these and other matters, please mail to:
+
+Project Gutenberg
+P. O. Box 2782
+Champaign, IL 61825
+
+When all other email fails try our Executive Director:
+Michael S. Hart
+
+We would prefer to send you this information by email
+(Internet, Bitnet, Compuserve, ATTMAIL or MCImail).
+
+******
+If you have an FTP program (or emulator), please
+FTP directly to the Project Gutenberg archives:
+[Mac users, do NOT point and click. . .type]
+
+ftp uiarchive.cso.uiuc.edu
+login: anonymous
+password: your@login
+cd etext/etext90 through /etext96
+or cd etext/articles [get suggest gut for more information]
+dir [to see files]
+get or mget [to get files. . .set bin for zip files]
+GET INDEX?00.GUT
+for a list of books
+and
+GET NEW GUT for general information
+and
+MGET GUT* for newsletters.
+
+**Information prepared by the Project Gutenberg legal advisor**
+(Three Pages)
+
+
+***START**THE SMALL PRINT!**FOR PUBLIC DOMAIN ETEXTS**START***
+Why is this "Small Print!" statement here? You know: lawyers.
+They tell us you might sue us if there is something wrong with
+your copy of this etext, even if you got it for free from
+someone other than us, and even if what's wrong is not our
+fault. So, among other things, this "Small Print!" statement
+disclaims most of our liability to you. It also tells you how
+you can distribute copies of this etext if you want to.
+
+*BEFORE!* YOU USE OR READ THIS ETEXT
+By using or reading any part of this PROJECT GUTENBERG-tm
+etext, you indicate that you understand, agree to and accept
+this "Small Print!" statement. If you do not, you can receive
+a refund of the money (if any) you paid for this etext by
+sending a request within 30 days of receiving it to the person
+you got it from. If you received this etext on a physical
+medium (such as a disk), you must return it with your request.
+
+ABOUT PROJECT GUTENBERG-TM ETEXTS
+This PROJECT GUTENBERG-tm etext, like most PROJECT GUTENBERG-
+tm etexts, is a "public domain" work distributed by Professor
+Michael S. Hart through the Project Gutenberg Association at
+Benedictine University (the "Project"). Among other
+things, this means that no one owns a United States copyright
+on or for this work, so the Project (and you!) can copy and
+distribute it in the United States without permission and
+without paying copyright royalties. Special rules, set forth
+below, apply if you wish to copy and distribute this etext
+under the Project's "PROJECT GUTENBERG" trademark.
+
+To create these etexts, the Project expends considerable
+efforts to identify, transcribe and proofread public domain
+works. Despite these efforts, the Project's etexts and any
+medium they may be on may contain "Defects". Among other
+things, Defects may take the form of incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other
+intellectual property infringement, a defective or damaged
+disk or other etext medium, a computer virus, or computer
+codes that damage or cannot be read by your equipment.
+
+LIMITED WARRANTY; DISCLAIMER OF DAMAGES
+But for the "Right of Replacement or Refund" described below,
+[1] the Project (and any other party you may receive this
+etext from as a PROJECT GUTENBERG-tm etext) disclaims all
+liability to you for damages, costs and expenses, including
+legal fees, and [2] YOU HAVE NO REMEDIES FOR NEGLIGENCE OR
+UNDER STRICT LIABILITY, OR FOR BREACH OF WARRANTY OR CONTRACT,
+INCLUDING BUT NOT LIMITED TO INDIRECT, CONSEQUENTIAL, PUNITIVE
+OR INCIDENTAL DAMAGES, EVEN IF YOU GIVE NOTICE OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+If you discover a Defect in this etext within 90 days of
+receiving it, you can receive a refund of the money (if any)
+you paid for it by sending an explanatory note within that
+time to the person you received it from. If you received it
+on a physical medium, you must return it with your note, and
+such person may choose to alternatively give you a replacement
+copy. If you received it electronically, such person may
+choose to alternatively give you a second opportunity to
+receive it electronically.
+
+THIS ETEXT IS OTHERWISE PROVIDED TO YOU "AS-IS". NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, ARE MADE TO YOU AS
+TO THE ETEXT OR ANY MEDIUM IT MAY BE ON, INCLUDING BUT NOT
+LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE.
+
+Some states do not allow disclaimers of implied warranties or
+the exclusion or limitation of consequential damages, so the
+above disclaimers and exclusions may not apply to you, and you
+may have other legal rights.
+
+INDEMNITY
+You will indemnify and hold the Project, its directors,
+officers, members and agents harmless from all liability, cost
+and expense, including legal fees, that arise directly or
+indirectly from any of the following that you do or cause:
+[1] distribution of this etext, [2] alteration, modification,
+or addition to the etext, or [3] any Defect.
+
+DISTRIBUTION UNDER "PROJECT GUTENBERG-tm"
+You may distribute copies of this etext electronically, or by
+disk, book or any other medium if you either delete this
+"Small Print!" and all other references to Project Gutenberg,
+or:
+
+[1] Only give exact copies of it. Among other things, this
+ requires that you do not remove, alter or modify the
+ etext or this "small print!" statement. You may however,
+ if you wish, distribute this etext in machine readable
+ binary, compressed, mark-up, or proprietary form,
+ including any form resulting from conversion by word pro-
+ cessing or hypertext software, but only so long as
+ *EITHER*:
+
+ [*] The etext, when displayed, is clearly readable, and
+ does *not* contain characters other than those
+ intended by the author of the work, although tilde
+ (~), asterisk (*) and underline (_) characters may
+ be used to convey punctuation intended by the
+ author, and additional characters may be used to
+ indicate hypertext links; OR
+
+ [*] The etext may be readily converted by the reader at
+ no expense into plain ASCII, EBCDIC or equivalent
+ form by the program that displays the etext (as is
+ the case, for instance, with most word processors);
+ OR
+
+ [*] You provide, or agree to also provide on request at
+ no additional cost, fee or expense, a copy of the
+ etext in its original plain ASCII form (or in EBCDIC
+ or other equivalent proprietary form).
+
+[2] Honor the etext refund and replacement provisions of this
+ "Small Print!" statement.
+
+[3] Pay a trademark license fee to the Project of 20% of the
+ net profits you derive calculated using the method you
+ already use to calculate your applicable taxes. If you
+ don't derive profits, no royalty is due. Royalties are
+ payable to "Project Gutenberg Association / Benedictine
+ University" within the 60 days following each
+ date you prepare (or were legally required to prepare)
+ your annual (or equivalent periodic) tax return.
+
+WHAT IF YOU *WANT* TO SEND MONEY EVEN IF YOU DON'T HAVE TO?
+The Project gratefully accepts contributions in money, time,
+scanning machines, OCR software, public domain etexts, royalty
+free copyright licenses, and every other sort of contribution
+you can think of. Money should be paid to "Project Gutenberg
+Association / Benedictine University".
+
+*END*THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END*
+
+
+
+
+
+A Child's History of England by Charles Dickens
+Scanned and Proofed by David Price, email ccx074@coventry.ac.uk
+
+
+
+
+
+A Child's History of England
+
+
+
+
+CHAPTER I - ANCIENT ENGLAND AND THE ROMANS
+
+
+
+IF you look at a Map of the World, you will see, in the left-hand
+upper corner of the Eastern Hemisphere, two Islands lying in the
+sea. They are England and Scotland, and Ireland. England and
+Scotland form the greater part of these Islands. Ireland is the
+next in size. The little neighbouring islands, which are so small
+upon the Map as to be mere dots, are chiefly little bits of
+Scotland, - broken off, I dare say, in the course of a great length
+of time, by the power of the restless water.
+
+In the old days, a long, long while ago, before Our Saviour was
+born on earth and lay asleep in a manger, these Islands were in the
+same place, and the stormy sea roared round them, just as it roars
+now. But the sea was not alive, then, with great ships and brave
+sailors, sailing to and from all parts of the world. It was very
+lonely. The Islands lay solitary, in the great expanse of water.
+The foaming waves dashed against their cliffs, and the bleak winds
+blew over their forests; but the winds and waves brought no
+adventurers to land upon the Islands, and the savage Islanders knew
+nothing of the rest of the world, and the rest of the world knew
+nothing of them.
+
+It is supposed that the Phoenicians, who were an ancient people,
+famous for carrying on trade, came in ships to these Islands, and
+found that they produced tin and lead; both very useful things, as
+you know, and both produced to this very hour upon the sea-coast.
+The most celebrated tin mines in Cornwall are, still, close to the
+sea. One of them, which I have seen, is so close to it that it is
+hollowed out underneath the ocean; and the miners say, that in
+stormy weather, when they are at work down in that deep place, they
+can hear the noise of the waves thundering above their heads. So,
+the Phoenicians, coasting about the Islands, would come, without
+much difficulty, to where the tin and lead were.
+
+The Phoenicians traded with the Islanders for these metals, and
+gave the Islanders some other useful things in exchange. The
+Islanders were, at first, poor savages, going almost naked, or only
+dressed in the rough skins of beasts, and staining their bodies, as
+other savages do, with coloured earths and the juices of plants.
+But the Phoenicians, sailing over to the opposite coasts of France
+and Belgium, and saying to the people there, 'We have been to those
+white cliffs across the water, which you can see in fine weather,
+and from that country, which is called BRITAIN, we bring this tin
+and lead,' tempted some of the French and Belgians to come over
+also. These people settled themselves on the south coast of
+England, which is now called Kent; and, although they were a rough
+people too, they taught the savage Britons some useful arts, and
+improved that part of the Islands. It is probable that other
+people came over from Spain to Ireland, and settled there.
+
+Thus, by little and little, strangers became mixed with the
+Islanders, and the savage Britons grew into a wild, bold people;
+almost savage, still, especially in the interior of the country
+away from the sea where the foreign settlers seldom went; but
+hardy, brave, and strong.
+
+The whole country was covered with forests, and swamps. The
+greater part of it was very misty and cold. There were no roads,
+no bridges, no streets, no houses that you would think deserving of
+the name. A town was nothing but a collection of straw-covered
+huts, hidden in a thick wood, with a ditch all round, and a low
+wall, made of mud, or the trunks of trees placed one upon another.
+The people planted little or no corn, but lived upon the flesh of
+their flocks and cattle. They made no coins, but used metal rings
+for money. They were clever in basket-work, as savage people often
+are; and they could make a coarse kind of cloth, and some very bad
+earthenware. But in building fortresses they were much more
+clever.
+
+They made boats of basket-work, covered with the skins of animals,
+but seldom, if ever, ventured far from the shore. They made
+swords, of copper mixed with tin; but, these swords were of an
+awkward shape, and so soft that a heavy blow would bend one. They
+made light shields, short pointed daggers, and spears - which they
+jerked back after they had thrown them at an enemy, by a long strip
+of leather fastened to the stem. The butt-end was a rattle, to
+frighten an enemy's horse. The ancient Britons, being divided into
+as many as thirty or forty tribes, each commanded by its own little
+king, were constantly fighting with one another, as savage people
+usually do; and they always fought with these weapons.
+
+They were very fond of horses. The standard of Kent was the
+picture of a white horse. They could break them in and manage them
+wonderfully well. Indeed, the horses (of which they had an
+abundance, though they were rather small) were so well taught in
+those days, that they can scarcely be said to have improved since;
+though the men are so much wiser. They understood, and obeyed,
+every word of command; and would stand still by themselves, in all
+the din and noise of battle, while their masters went to fight on
+foot. The Britons could not have succeeded in their most
+remarkable art, without the aid of these sensible and trusty
+animals. The art I mean, is the construction and management of
+war-chariots or cars, for which they have ever been celebrated in
+history. Each of the best sort of these chariots, not quite breast
+high in front, and open at the back, contained one man to drive,
+and two or three others to fight - all standing up. The horses who
+drew them were so well trained, that they would tear, at full
+gallop, over the most stony ways, and even through the woods;
+dashing down their masters' enemies beneath their hoofs, and
+cutting them to pieces with the blades of swords, or scythes, which
+were fastened to the wheels, and stretched out beyond the car on
+each side, for that cruel purpose. In a moment, while at full
+speed, the horses would stop, at the driver's command. The men
+within would leap out, deal blows about them with their swords like
+hail, leap on the horses, on the pole, spring back into the
+chariots anyhow; and, as soon as they were safe, the horses tore
+away again.
+
+The Britons had a strange and terrible religion, called the
+Religion of the Druids. It seems to have been brought over, in
+very early times indeed, from the opposite country of France,
+anciently called Gaul, and to have mixed up the worship of the
+Serpent, and of the Sun and Moon, with the worship of some of the
+Heathen Gods and Goddesses. Most of its ceremonies were kept
+secret by the priests, the Druids, who pretended to be enchanters,
+and who carried magicians' wands, and wore, each of them, about his
+neck, what he told the ignorant people was a Serpent's egg in a
+golden case. But it is certain that the Druidical ceremonies
+included the sacrifice of human victims, the torture of some
+suspected criminals, and, on particular occasions, even the burning
+alive, in immense wicker cages, of a number of men and animals
+together. The Druid Priests had some kind of veneration for the
+Oak, and for the mistletoe - the same plant that we hang up in
+houses at Christmas Time now - when its white berries grew upon the
+Oak. They met together in dark woods, which they called Sacred
+Groves; and there they instructed, in their mysterious arts, young
+men who came to them as pupils, and who sometimes stayed with them
+as long as twenty years.
+
+These Druids built great Temples and altars, open to the sky,
+fragments of some of which are yet remaining. Stonehenge, on
+Salisbury Plain, in Wiltshire, is the most extraordinary of these.
+Three curious stones, called Kits Coty House, on Bluebell Hill,
+near Maidstone, in Kent, form another. We know, from examination
+of the great blocks of which such buildings are made, that they
+could not have been raised without the aid of some ingenious
+machines, which are common now, but which the ancient Britons
+certainly did not use in making their own uncomfortable houses. I
+should not wonder if the Druids, and their pupils who stayed with
+them twenty years, knowing more than the rest of the Britons, kept
+the people out of sight while they made these buildings, and then
+pretended that they built them by magic. Perhaps they had a hand
+in the fortresses too; at all events, as they were very powerful,
+and very much believed in, and as they made and executed the laws,
+and paid no taxes, I don't wonder that they liked their trade.
+And, as they persuaded the people the more Druids there were, the
+better off the people would be, I don't wonder that there were a
+good many of them. But it is pleasant to think that there are no
+Druids, NOW, who go on in that way, and pretend to carry
+Enchanters' Wands and Serpents' Eggs - and of course there is
+nothing of the kind, anywhere.
+
+Such was the improved condition of the ancient Britons, fifty-five
+years before the birth of Our Saviour, when the Romans, under their
+great General, Julius Caesar, were masters of all the rest of the
+known world. Julius Caesar had then just conquered Gaul; and
+hearing, in Gaul, a good deal about the opposite Island with the
+white cliffs, and about the bravery of the Britons who inhabited it
+- some of whom had been fetched over to help the Gauls in the war
+against him - he resolved, as he was so near, to come and conquer
+Britain next.
+
+So, Julius Caesar came sailing over to this Island of ours, with
+eighty vessels and twelve thousand men. And he came from the
+French coast between Calais and Boulogne, 'because thence was the
+shortest passage into Britain;' just for the same reason as our
+steam-boats now take the same track, every day. He expected to
+conquer Britain easily: but it was not such easy work as he
+supposed - for the bold Britons fought most bravely; and, what with
+not having his horse-soldiers with him (for they had been driven
+back by a storm), and what with having some of his vessels dashed
+to pieces by a high tide after they were drawn ashore, he ran great
+risk of being totally defeated. However, for once that the bold
+Britons beat him, he beat them twice; though not so soundly but
+that he was very glad to accept their proposals of peace, and go
+away.
+
+But, in the spring of the next year, he came back; this time, with
+eight hundred vessels and thirty thousand men. The British tribes
+chose, as their general-in-chief, a Briton, whom the Romans in
+their Latin language called CASSIVELLAUNUS, but whose British name
+is supposed to have been CASWALLON. A brave general he was, and
+well he and his soldiers fought the Roman army! So well, that
+whenever in that war the Roman soldiers saw a great cloud of dust,
+and heard the rattle of the rapid British chariots, they trembled
+in their hearts. Besides a number of smaller battles, there was a
+battle fought near Canterbury, in Kent; there was a battle fought
+near Chertsey, in Surrey; there was a battle fought near a marshy
+little town in a wood, the capital of that part of Britain which
+belonged to CASSIVELLAUNUS, and which was probably near what is now
+Saint Albans, in Hertfordshire. However, brave CASSIVELLAUNUS had
+the worst of it, on the whole; though he and his men always fought
+like lions. As the other British chiefs were jealous of him, and
+were always quarrelling with him, and with one another, he gave up,
+and proposed peace. Julius Caesar was very glad to grant peace
+easily, and to go away again with all his remaining ships and men.
+He had expected to find pearls in Britain, and he may have found a
+few for anything I know; but, at all events, he found delicious
+oysters, and I am sure he found tough Britons - of whom, I dare
+say, he made the same complaint as Napoleon Bonaparte the great
+French General did, eighteen hundred years afterwards, when he said
+they were such unreasonable fellows that they never knew when they
+were beaten. They never DID know, I believe, and never will.
+
+Nearly a hundred years passed on, and all that time, there was
+peace in Britain. The Britons improved their towns and mode of
+life: became more civilised, travelled, and learnt a great deal
+from the Gauls and Romans. At last, the Roman Emperor, Claudius,
+sent AULUS PLAUTIUS, a skilful general, with a mighty force, to
+subdue the Island, and shortly afterwards arrived himself. They
+did little; and OSTORIUS SCAPULA, another general, came. Some of
+the British Chiefs of Tribes submitted. Others resolved to fight
+to the death. Of these brave men, the bravest was CARACTACUS, or
+CARADOC, who gave battle to the Romans, with his army, among the
+mountains of North Wales. 'This day,' said he to his soldiers,
+'decides the fate of Britain! Your liberty, or your eternal
+slavery, dates from this hour. Remember your brave ancestors, who
+drove the great Caesar himself across the sea!' On hearing these
+words, his men, with a great shout, rushed upon the Romans. But
+the strong Roman swords and armour were too much for the weaker
+British weapons in close conflict. The Britons lost the day. The
+wife and daughter of the brave CARACTACUS were taken prisoners; his
+brothers delivered themselves up; he himself was betrayed into the
+hands of the Romans by his false and base stepmother: and they
+carried him, and all his family, in triumph to Rome.
+
+But a great man will be great in misfortune, great in prison, great
+in chains. His noble air, and dignified endurance of distress, so
+touched the Roman people who thronged the streets to see him, that
+he and his family were restored to freedom. No one knows whether
+his great heart broke, and he died in Rome, or whether he ever
+returned to his own dear country. English oaks have grown up from
+acorns, and withered away, when they were hundreds of years old -
+and other oaks have sprung up in their places, and died too, very
+aged - since the rest of the history of the brave CARACTACUS was
+forgotten.
+
+Still, the Britons WOULD NOT yield. They rose again and again, and
+died by thousands, sword in hand. They rose, on every possible
+occasion. SUETONIUS, another Roman general, came, and stormed the
+Island of Anglesey (then called MONA), which was supposed to be
+sacred, and he burnt the Druids in their own wicker cages, by their
+own fires. But, even while he was in Britain, with his victorious
+troops, the BRITONS rose. Because BOADICEA, a British queen, the
+widow of the King of the Norfolk and Suffolk people, resisted the
+plundering of her property by the Romans who were settled in
+England, she was scourged, by order of CATUS a Roman officer; and
+her two daughters were shamefully insulted in her presence, and her
+husband's relations were made slaves. To avenge this injury, the
+Britons rose, with all their might and rage. They drove CATUS into
+Gaul; they laid the Roman possessions waste; they forced the Romans
+out of London, then a poor little town, but a trading place; they
+hanged, burnt, crucified, and slew by the sword, seventy thousand
+Romans in a few days. SUETONIUS strengthened his army, and
+advanced to give them battle. They strengthened their army, and
+desperately attacked his, on the field where it was strongly
+posted. Before the first charge of the Britons was made, BOADICEA,
+in a war-chariot, with her fair hair streaming in the wind, and her
+injured daughters lying at her feet, drove among the troops, and
+cried to them for vengeance on their oppressors, the licentious
+Romans. The Britons fought to the last; but they were vanquished
+with great slaughter, and the unhappy queen took poison.
+
+Still, the spirit of the Britons was not broken. When SUETONIUS
+left the country, they fell upon his troops, and retook the Island
+of Anglesey. AGRICOLA came, fifteen or twenty years afterwards,
+and retook it once more, and devoted seven years to subduing the
+country, especially that part of it which is now called SCOTLAND;
+but, its people, the Caledonians, resisted him at every inch of
+ground. They fought the bloodiest battles with him; they killed
+their very wives and children, to prevent his making prisoners of
+them; they fell, fighting, in such great numbers that certain hills
+in Scotland are yet supposed to be vast heaps of stones piled up
+above their graves. HADRIAN came, thirty years afterwards, and
+still they resisted him. SEVERUS came, nearly a hundred years
+afterwards, and they worried his great army like dogs, and rejoiced
+to see them die, by thousands, in the bogs and swamps. CARACALLA,
+the son and successor of SEVERUS, did the most to conquer them, for
+a time; but not by force of arms. He knew how little that would
+do. He yielded up a quantity of land to the Caledonians, and gave
+the Britons the same privileges as the Romans possessed. There was
+peace, after this, for seventy years.
+
+Then new enemies arose. They were the Saxons, a fierce, sea-faring
+people from the countries to the North of the Rhine, the great
+river of Germany on the banks of which the best grapes grow to make
+the German wine. They began to come, in pirate ships, to the sea-
+coast of Gaul and Britain, and to plunder them. They were repulsed
+by CARAUSIUS, a native either of Belgium or of Britain, who was
+appointed by the Romans to the command, and under whom the Britons
+first began to fight upon the sea. But, after this time, they
+renewed their ravages. A few years more, and the Scots (which was
+then the name for the people of Ireland), and the Picts, a northern
+people, began to make frequent plundering incursions into the South
+of Britain. All these attacks were repeated, at intervals, during
+two hundred years, and through a long succession of Roman Emperors
+and chiefs; during all which length of time, the Britons rose
+against the Romans, over and over again. At last, in the days of
+the Roman HONORIUS, when the Roman power all over the world was
+fast declining, and when Rome wanted all her soldiers at home, the
+Romans abandoned all hope of conquering Britain, and went away.
+And still, at last, as at first, the Britons rose against them, in
+their old brave manner; for, a very little while before, they had
+turned away the Roman magistrates, and declared themselves an
+independent people.
+
+Five hundred years had passed, since Julius Caesar's first invasion
+of the Island, when the Romans departed from it for ever. In the
+course of that time, although they had been the cause of terrible
+fighting and bloodshed, they had done much to improve the condition
+of the Britons. They had made great military roads; they had built
+forts; they had taught them how to dress, and arm themselves, much
+better than they had ever known how to do before; they had refined
+the whole British way of living. AGRICOLA had built a great wall
+of earth, more than seventy miles long, extending from Newcastle to
+beyond Carlisle, for the purpose of keeping out the Picts and
+Scots; HADRIAN had strengthened it; SEVERUS, finding it much in
+want of repair, had built it afresh of stone.
+
+Above all, it was in the Roman time, and by means of Roman ships,
+that the Christian Religion was first brought into Britain, and its
+people first taught the great lesson that, to be good in the sight
+of GOD, they must love their neighbours as themselves, and do unto
+others as they would be done by. The Druids declared that it was
+very wicked to believe in any such thing, and cursed all the people
+who did believe it, very heartily. But, when the people found that
+they were none the better for the blessings of the Druids, and none
+the worse for the curses of the Druids, but, that the sun shone and
+the rain fell without consulting the Druids at all, they just began
+to think that the Druids were mere men, and that it signified very
+little whether they cursed or blessed. After which, the pupils of
+the Druids fell off greatly in numbers, and the Druids took to
+other trades.
+
+Thus I have come to the end of the Roman time in England. It is
+but little that is known of those five hundred years; but some
+remains of them are still found. Often, when labourers are digging
+up the ground, to make foundations for houses or churches, they
+light on rusty money that once belonged to the Romans. Fragments
+of plates from which they ate, of goblets from which they drank,
+and of pavement on which they trod, are discovered among the earth
+that is broken by the plough, or the dust that is crumbled by the
+gardener's spade. Wells that the Romans sunk, still yield water;
+roads that the Romans made, form part of our highways. In some old
+battle-fields, British spear-heads and Roman armour have been
+found, mingled together in decay, as they fell in the thick
+pressure of the fight. Traces of Roman camps overgrown with grass,
+and of mounds that are the burial-places of heaps of Britons, are
+to be seen in almost all parts of the country. Across the bleak
+moors of Northumberland, the wall of SEVERUS, overrun with moss and
+weeds, still stretches, a strong ruin; and the shepherds and their
+dogs lie sleeping on it in the summer weather. On Salisbury Plain,
+Stonehenge yet stands: a monument of the earlier time when the
+Roman name was unknown in Britain, and when the Druids, with their
+best magic wands, could not have written it in the sands of the
+wild sea-shore.
+
+
+
+CHAPTER II - ANCIENT ENGLAND UNDER THE EARLY SAXONS
+
+
+
+THE Romans had scarcely gone away from Britain, when the Britons
+began to wish they had never left it. For, the Romans being gone,
+and the Britons being much reduced in numbers by their long wars,
+the Picts and Scots came pouring in, over the broken and unguarded
+wall of SEVERUS, in swarms. They plundered the richest towns, and
+killed the people; and came back so often for more booty and more
+slaughter, that the unfortunate Britons lived a life of terror. As
+if the Picts and Scots were not bad enough on land, the Saxons
+attacked the islanders by sea; and, as if something more were still
+wanting to make them miserable, they quarrelled bitterly among
+themselves as to what prayers they ought to say, and how they ought
+to say them. The priests, being very angry with one another on
+these questions, cursed one another in the heartiest manner; and
+(uncommonly like the old Druids) cursed all the people whom they
+could not persuade. So, altogether, the Britons were very badly
+off, you may believe.
+
+They were in such distress, in short, that they sent a letter to
+Rome entreating help - which they called the Groans of the Britons;
+and in which they said, 'The barbarians chase us into the sea, the
+sea throws us back upon the barbarians, and we have only the hard
+choice left us of perishing by the sword, or perishing by the
+waves.' But, the Romans could not help them, even if they were so
+inclined; for they had enough to do to defend themselves against
+their own enemies, who were then very fierce and strong. At last,
+the Britons, unable to bear their hard condition any longer,
+resolved to make peace with the Saxons, and to invite the Saxons to
+come into their country, and help them to keep out the Picts and
+Scots.
+
+It was a British Prince named VORTIGERN who took this resolution,
+and who made a treaty of friendship with HENGIST and HORSA, two
+Saxon chiefs. Both of these names, in the old Saxon language,
+signify Horse; for the Saxons, like many other nations in a rough
+state, were fond of giving men the names of animals, as Horse,
+Wolf, Bear, Hound. The Indians of North America, - a very inferior
+people to the Saxons, though - do the same to this day.
+
+HENGIST and HORSA drove out the Picts and Scots; and VORTIGERN,
+being grateful to them for that service, made no opposition to
+their settling themselves in that part of England which is called
+the Isle of Thanet, or to their inviting over more of their
+countrymen to join them. But HENGIST had a beautiful daughter
+named ROWENA; and when, at a feast, she filled a golden goblet to
+the brim with wine, and gave it to VORTIGERN, saying in a sweet
+voice, 'Dear King, thy health!' the King fell in love with her. My
+opinion is, that the cunning HENGIST meant him to do so, in order
+that the Saxons might have greater influence with him; and that the
+fair ROWENA came to that feast, golden goblet and all, on purpose.
+
+At any rate, they were married; and, long afterwards, whenever the
+King was angry with the Saxons, or jealous of their encroachments,
+ROWENA would put her beautiful arms round his neck, and softly say,
+'Dear King, they are my people! Be favourable to them, as you
+loved that Saxon girl who gave you the golden goblet of wine at the
+feast!' And, really, I don't see how the King could help himself.
+
+Ah! We must all die! In the course of years, VORTIGERN died - he
+was dethroned, and put in prison, first, I am afraid; and ROWENA
+died; and generations of Saxons and Britons died; and events that
+happened during a long, long time, would have been quite forgotten
+but for the tales and songs of the old Bards, who used to go about
+from feast to feast, with their white beards, recounting the deeds
+of their forefathers. Among the histories of which they sang and
+talked, there was a famous one, concerning the bravery and virtues
+of KING ARTHUR, supposed to have been a British Prince in those old
+times. But, whether such a person really lived, or whether there
+were several persons whose histories came to be confused together
+under that one name, or whether all about him was invention, no one
+knows.
+
+I will tell you, shortly, what is most interesting in the early
+Saxon times, as they are described in these songs and stories of
+the Bards.
+
+In, and long after, the days of VORTIGERN, fresh bodies of Saxons,
+under various chiefs, came pouring into Britain. One body,
+conquering the Britons in the East, and settling there, called
+their kingdom Essex; another body settled in the West, and called
+their kingdom Wessex; the Northfolk, or Norfolk people, established
+themselves in one place; the Southfolk, or Suffolk people,
+established themselves in another; and gradually seven kingdoms or
+states arose in England, which were called the Saxon Heptarchy.
+The poor Britons, falling back before these crowds of fighting men
+whom they had innocently invited over as friends, retired into
+Wales and the adjacent country; into Devonshire, and into Cornwall.
+Those parts of England long remained unconquered. And in Cornwall
+now - where the sea-coast is very gloomy, steep, and rugged -
+where, in the dark winter-time, ships have often been wrecked close
+to the land, and every soul on board has perished - where the winds
+and waves howl drearily and split the solid rocks into arches and
+caverns - there are very ancient ruins, which the people call the
+ruins of KING ARTHUR'S Castle.
+
+Kent is the most famous of the seven Saxon kingdoms, because the
+Christian religion was preached to the Saxons there (who domineered
+over the Britons too much, to care for what THEY said about their
+religion, or anything else) by AUGUSTINE, a monk from Rome. KING
+ETHELBERT, of Kent, was soon converted; and the moment he said he
+was a Christian, his courtiers all said THEY were Christians; after
+which, ten thousand of his subjects said they were Christians too.
+AUGUSTINE built a little church, close to this King's palace, on
+the ground now occupied by the beautiful cathedral of Canterbury.
+SEBERT, the King's nephew, built on a muddy marshy place near
+London, where there had been a temple to Apollo, a church dedicated
+to Saint Peter, which is now Westminster Abbey. And, in London
+itself, on the foundation of a temple to Diana, he built another
+little church which has risen up, since that old time, to be Saint
+Paul's.
+
+After the death of ETHELBERT, EDWIN, King of Northumbria, who was
+such a good king that it was said a woman or child might openly
+carry a purse of gold, in his reign, without fear, allowed his
+child to be baptised, and held a great council to consider whether
+he and his people should all be Christians or not. It was decided
+that they should be. COIFI, the chief priest of the old religion,
+made a great speech on the occasion. In this discourse, he told
+the people that he had found out the old gods to be impostors. 'I
+am quite satisfied of it,' he said. 'Look at me! I have been
+serving them all my life, and they have done nothing for me;
+whereas, if they had been really powerful, they could not have
+decently done less, in return for all I have done for them, than
+make my fortune. As they have never made my fortune, I am quite
+convinced they are impostors!' When this singular priest had
+finished speaking, he hastily armed himself with sword and lance,
+mounted a war-horse, rode at a furious gallop in sight of all the
+people to the temple, and flung his lance against it as an insult.
+From that time, the Christian religion spread itself among the
+Saxons, and became their faith.
+
+The next very famous prince was EGBERT. He lived about a hundred
+and fifty years afterwards, and claimed to have a better right to
+the throne of Wessex than BEORTRIC, another Saxon prince who was at
+the head of that kingdom, and who married EDBURGA, the daughter of
+OFFA, king of another of the seven kingdoms. This QUEEN EDBURGA
+was a handsome murderess, who poisoned people when they offended
+her. One day, she mixed a cup of poison for a certain noble
+belonging to the court; but her husband drank of it too, by
+mistake, and died. Upon this, the people revolted, in great
+crowds; and running to the palace, and thundering at the gates,
+cried, 'Down with the wicked queen, who poisons men!' They drove
+her out of the country, and abolished the title she had disgraced.
+When years had passed away, some travellers came home from Italy,
+and said that in the town of Pavia they had seen a ragged beggar-
+woman, who had once been handsome, but was then shrivelled, bent,
+and yellow, wandering about the streets, crying for bread; and that
+this beggar-woman was the poisoning English queen. It was, indeed,
+EDBURGA; and so she died, without a shelter for her wretched head.
+
+EGBERT, not considering himself safe in England, in consequence of
+his having claimed the crown of Wessex (for he thought his rival
+might take him prisoner and put him to death), sought refuge at the
+court of CHARLEMAGNE, King of France. On the death of BEORTRIC, so
+unhappily poisoned by mistake, EGBERT came back to Britain;
+succeeded to the throne of Wessex; conquered some of the other
+monarchs of the seven kingdoms; added their territories to his own;
+and, for the first time, called the country over which he ruled,
+ENGLAND.
+
+And now, new enemies arose, who, for a long time, troubled England
+sorely. These were the Northmen, the people of Denmark and Norway,
+whom the English called the Danes. They were a warlike people,
+quite at home upon the sea; not Christians; very daring and cruel.
+They came over in ships, and plundered and burned wheresoever they
+landed. Once, they beat EGBERT in battle. Once, EGBERT beat them.
+But, they cared no more for being beaten than the English
+themselves. In the four following short reigns, of ETHELWULF, and
+his sons, ETHELBALD, ETHELBERT, and ETHELRED, they came back, over
+and over again, burning and plundering, and laying England waste.
+In the last-mentioned reign, they seized EDMUND, King of East
+England, and bound him to a tree. Then, they proposed to him that
+he should change his religion; but he, being a good Christian,
+steadily refused. Upon that, they beat him, made cowardly jests
+upon him, all defenceless as he was, shot arrows at him, and,
+finally, struck off his head. It is impossible to say whose head
+they might have struck off next, but for the death of KING ETHELRED
+from a wound he had received in fighting against them, and the
+succession to his throne of the best and wisest king that ever
+lived in England.
+
+
+
+CHAPTER III - ENGLAND UNDER THE GOOD SAXON, ALFRED
+
+
+
+ALFRED THE GREAT was a young man, three-and-twenty years of age,
+when he became king. Twice in his childhood, he had been taken to
+Rome, where the Saxon nobles were in the habit of going on journeys
+which they supposed to be religious; and, once, he had stayed for
+some time in Paris. Learning, however, was so little cared for,
+then, that at twelve years old he had not been taught to read;
+although, of the sons of KING ETHELWULF, he, the youngest, was the
+favourite. But he had - as most men who grow up to be great and
+good are generally found to have had - an excellent mother; and,
+one day, this lady, whose name was OSBURGA, happened, as she was
+sitting among her sons, to read a book of Saxon poetry. The art of
+printing was not known until long and long after that period, and
+the book, which was written, was what is called 'illuminated,' with
+beautiful bright letters, richly painted. The brothers admiring it
+very much, their mother said, 'I will give it to that one of you
+four princes who first learns to read.' ALFRED sought out a tutor
+that very day, applied himself to learn with great diligence, and
+soon won the book. He was proud of it, all his life.
+
+This great king, in the first year of his reign, fought nine
+battles with the Danes. He made some treaties with them too, by
+which the false Danes swore they would quit the country. They
+pretended to consider that they had taken a very solemn oath, in
+swearing this upon the holy bracelets that they wore, and which
+were always buried with them when they died; but they cared little
+for it, for they thought nothing of breaking oaths and treaties
+too, as soon as it suited their purpose, and coming back again to
+fight, plunder, and burn, as usual. One fatal winter, in the
+fourth year of KING ALFRED'S reign, they spread themselves in great
+numbers over the whole of England; and so dispersed and routed the
+King's soldiers that the King was left alone, and was obliged to
+disguise himself as a common peasant, and to take refuge in the
+cottage of one of his cowherds who did not know his face.
+
+Here, KING ALFRED, while the Danes sought him far and near, was
+left alone one day, by the cowherd's wife, to watch some cakes
+which she put to bake upon the hearth. But, being at work upon his
+bow and arrows, with which he hoped to punish the false Danes when
+a brighter time should come, and thinking deeply of his poor
+unhappy subjects whom the Danes chased through the land, his noble
+mind forgot the cakes, and they were burnt. 'What!' said the
+cowherd's wife, who scolded him well when she came back, and little
+thought she was scolding the King, 'you will be ready enough to eat
+them by-and-by, and yet you cannot watch them, idle dog?'
+
+At length, the Devonshire men made head against a new host of Danes
+who landed on their coast; killed their chief, and captured their
+flag; on which was represented the likeness of a Raven - a very fit
+bird for a thievish army like that, I think. The loss of their
+standard troubled the Danes greatly, for they believed it to be
+enchanted - woven by the three daughters of one father in a single
+afternoon - and they had a story among themselves that when they
+were victorious in battle, the Raven stretched his wings and seemed
+to fly; and that when they were defeated, he would droop. He had
+good reason to droop, now, if he could have done anything half so
+sensible; for, KING ALFRED joined the Devonshire men; made a camp
+with them on a piece of firm ground in the midst of a bog in
+Somersetshire; and prepared for a great attempt for vengeance on
+the Danes, and the deliverance of his oppressed people.
+
+But, first, as it was important to know how numerous those
+pestilent Danes were, and how they were fortified, KING ALFRED,
+being a good musician, disguised himself as a glee-man or minstrel,
+and went, with his harp, to the Danish camp. He played and sang in
+the very tent of GUTHRUM the Danish leader, and entertained the
+Danes as they caroused. While he seemed to think of nothing but
+his music, he was watchful of their tents, their arms, their
+discipline, everything that he desired to know. And right soon did
+this great king entertain them to a different tune; for, summoning
+all his true followers to meet him at an appointed place, where
+they received him with joyful shouts and tears, as the monarch whom
+many of them had given up for lost or dead, he put himself at their
+head, marched on the Danish camp, defeated the Danes with great
+slaughter, and besieged them for fourteen days to prevent their
+escape. But, being as merciful as he was good and brave, he then,
+instead of killing them, proposed peace: on condition that they
+should altogether depart from that Western part of England, and
+settle in the East; and that GUTHRUM should become a Christian, in
+remembrance of the Divine religion which now taught his conqueror,
+the noble ALFRED, to forgive the enemy who had so often injured
+him. This, GUTHRUM did. At his baptism, KING ALFRED was his
+godfather. And GUTHRUM was an honourable chief who well deserved
+that clemency; for, ever afterwards he was loyal and faithful to
+the king. The Danes under him were faithful too. They plundered
+and burned no more, but worked like honest men. They ploughed, and
+sowed, and reaped, and led good honest English lives. And I hope
+the children of those Danes played, many a time, with Saxon
+children in the sunny fields; and that Danish young men fell in
+love with Saxon girls, and married them; and that English
+travellers, benighted at the doors of Danish cottages, often went
+in for shelter until morning; and that Danes and Saxons sat by the
+red fire, friends, talking of KING ALFRED THE GREAT.
+
+All the Danes were not like these under GUTHRUM; for, after some
+years, more of them came over, in the old plundering and burning
+way - among them a fierce pirate of the name of HASTINGS, who had
+the boldness to sail up the Thames to Gravesend, with eighty ships.
+For three years, there was a war with these Danes; and there was a
+famine in the country, too, and a plague, both upon human creatures
+and beasts. But KING ALFRED, whose mighty heart never failed him,
+built large ships nevertheless, with which to pursue the pirates on
+the sea; and he encouraged his soldiers, by his brave example, to
+fight valiantly against them on the shore. At last, he drove them
+all away; and then there was repose in England.
+
+As great and good in peace, as he was great and good in war, KING
+ALFRED never rested from his labours to improve his people. He
+loved to talk with clever men, and with travellers from foreign
+countries, and to write down what they told him, for his people to
+read. He had studied Latin after learning to read English, and now
+another of his labours was, to translate Latin books into the
+English-Saxon tongue, that his people might be interested, and
+improved by their contents. He made just laws, that they might
+live more happily and freely; he turned away all partial judges,
+that no wrong might be done them; he was so careful of their
+property, and punished robbers so severely, that it was a common
+thing to say that under the great KING ALFRED, garlands of golden
+chains and jewels might have hung across the streets, and no man
+would have touched one. He founded schools; he patiently heard
+causes himself in his Court of Justice; the great desires of his
+heart were, to do right to all his subjects, and to leave England
+better, wiser, happier in all ways, than he found it. His industry
+in these efforts was quite astonishing. Every day he divided into
+certain portions, and in each portion devoted himself to a certain
+pursuit. That he might divide his time exactly, he had wax torches
+or candles made, which were all of the same size, were notched
+across at regular distances, and were always kept burning. Thus,
+as the candles burnt down, he divided the day into notches, almost
+as accurately as we now divide it into hours upon the clock. But
+when the candles were first invented, it was found that the wind
+and draughts of air, blowing into the palace through the doors and
+windows, and through the chinks in the walls, caused them to gutter
+and burn unequally. To prevent this, the King had them put into
+cases formed of wood and white horn. And these were the first
+lanthorns ever made in England.
+
+All this time, he was afflicted with a terrible unknown disease,
+which caused him violent and frequent pain that nothing could
+relieve. He bore it, as he had borne all the troubles of his life,
+like a brave good man, until he was fifty-three years old; and
+then, having reigned thirty years, he died. He died in the year
+nine hundred and one; but, long ago as that is, his fame, and the
+love and gratitude with which his subjects regarded him, are
+freshly remembered to the present hour.
+
+In the next reign, which was the reign of EDWARD, surnamed THE
+ELDER, who was chosen in council to succeed, a nephew of KING
+ALFRED troubled the country by trying to obtain the throne. The
+Danes in the East of England took part with this usurper (perhaps
+because they had honoured his uncle so much, and honoured him for
+his uncle's sake), and there was hard fighting; but, the King, with
+the assistance of his sister, gained the day, and reigned in peace
+for four and twenty years. He gradually extended his power over
+the whole of England, and so the Seven Kingdoms were united into
+one.
+
+When England thus became one kingdom, ruled over by one Saxon king,
+the Saxons had been settled in the country more than four hundred
+and fifty years. Great changes had taken place in its customs
+during that time. The Saxons were still greedy eaters and great
+drinkers, and their feasts were often of a noisy and drunken kind;
+but many new comforts and even elegances had become known, and were
+fast increasing. Hangings for the walls of rooms, where, in these
+modern days, we paste up paper, are known to have been sometimes
+made of silk, ornamented with birds and flowers in needlework.
+Tables and chairs were curiously carved in different woods; were
+sometimes decorated with gold or silver; sometimes even made of
+those precious metals. Knives and spoons were used at table;
+golden ornaments were worn - with silk and cloth, and golden
+tissues and embroideries; dishes were made of gold and silver,
+brass and bone. There were varieties of drinking-horns, bedsteads,
+musical instruments. A harp was passed round, at a feast, like the
+drinking-bowl, from guest to guest; and each one usually sang or
+played when his turn came. The weapons of the Saxons were stoutly
+made, and among them was a terrible iron hammer that gave deadly
+blows, and was long remembered. The Saxons themselves were a
+handsome people. The men were proud of their long fair hair,
+parted on the forehead; their ample beards, their fresh
+complexions, and clear eyes. The beauty of the Saxon women filled
+all England with a new delight and grace.
+
+I have more to tell of the Saxons yet, but I stop to say this now,
+because under the GREAT ALFRED, all the best points of the English-
+Saxon character were first encouraged, and in him first shown. It
+has been the greatest character among the nations of the earth.
+Wherever the descendants of the Saxon race have gone, have sailed,
+or otherwise made their way, even to the remotest regions of the
+world, they have been patient, persevering, never to be broken in
+spirit, never to be turned aside from enterprises on which they
+have resolved. In Europe, Asia, Africa, America, the whole world
+over; in the desert, in the forest, on the sea; scorched by a
+burning sun, or frozen by ice that never melts; the Saxon blood
+remains unchanged. Wheresoever that race goes, there, law, and
+industry, and safety for life and property, and all the great
+results of steady perseverance, are certain to arise.
+
+I pause to think with admiration, of the noble king who, in his
+single person, possessed all the Saxon virtues. Whom misfortune
+could not subdue, whom prosperity could not spoil, whose
+perseverance nothing could shake. Who was hopeful in defeat, and
+generous in success. Who loved justice, freedom, truth, and
+knowledge. Who, in his care to instruct his people, probably did
+more to preserve the beautiful old Saxon language, than I can
+imagine. Without whom, the English tongue in which I tell this
+story might have wanted half its meaning. As it is said that his
+spirit still inspires some of our best English laws, so, let you
+and I pray that it may animate our English hearts, at least to this
+- to resolve, when we see any of our fellow-creatures left in
+ignorance, that we will do our best, while life is in us, to have
+them taught; and to tell those rulers whose duty it is to teach
+them, and who neglect their duty, that they have profited very
+little by all the years that have rolled away since the year nine
+hundred and one, and that they are far behind the bright example of
+KING ALFRED THE GREAT.
+
+
+
+CHAPTER IV - ENGLAND UNDER ATHELSTAN AND THE SIX BOY-KINGS
+
+
+
+ATHELSTAN, the son of Edward the Elder, succeeded that king. He
+reigned only fifteen years; but he remembered the glory of his
+grandfather, the great Alfred, and governed England well. He
+reduced the turbulent people of Wales, and obliged them to pay him
+a tribute in money, and in cattle, and to send him their best hawks
+and hounds. He was victorious over the Cornish men, who were not
+yet quite under the Saxon government. He restored such of the old
+laws as were good, and had fallen into disuse; made some wise new
+laws, and took care of the poor and weak. A strong alliance, made
+against him by ANLAF a Danish prince, CONSTANTINE King of the
+Scots, and the people of North Wales, he broke and defeated in one
+great battle, long famous for the vast numbers slain in it. After
+that, he had a quiet reign; the lords and ladies about him had
+leisure to become polite and agreeable; and foreign princes were
+glad (as they have sometimes been since) to come to England on
+visits to the English court.
+
+When Athelstan died, at forty-seven years old, his brother EDMUND,
+who was only eighteen, became king. He was the first of six boy-
+kings, as you will presently know.
+
+They called him the Magnificent, because he showed a taste for
+improvement and refinement. But he was beset by the Danes, and had
+a short and troubled reign, which came to a troubled end. One
+night, when he was feasting in his hall, and had eaten much and
+drunk deep, he saw, among the company, a noted robber named LEOF,
+who had been banished from England. Made very angry by the
+boldness of this man, the King turned to his cup-bearer, and said,
+'There is a robber sitting at the table yonder, who, for his
+crimes, is an outlaw in the land - a hunted wolf, whose life any
+man may take, at any time. Command that robber to depart!' 'I
+will not depart!' said Leof. 'No?' cried the King. 'No, by the
+Lord!' said Leof. Upon that the King rose from his seat, and,
+making passionately at the robber, and seizing him by his long
+hair, tried to throw him down. But the robber had a dagger
+underneath his cloak, and, in the scuffle, stabbed the King to
+death. That done, he set his back against the wall, and fought so
+desperately, that although he was soon cut to pieces by the King's
+armed men, and the wall and pavement were splashed with his blood,
+yet it was not before he had killed and wounded many of them. You
+may imagine what rough lives the kings of those times led, when one
+of them could struggle, half drunk, with a public robber in his own
+dining-hall, and be stabbed in presence of the company who ate and
+drank with him.
+
+Then succeeded the boy-king EDRED, who was weak and sickly in body,
+but of a strong mind. And his armies fought the Northmen, the
+Danes, and Norwegians, or the Sea-Kings, as they were called, and
+beat them for the time. And, in nine years, Edred died, and passed
+away.
+
+Then came the boy-king EDWY, fifteen years of age; but the real
+king, who had the real power, was a monk named DUNSTAN - a clever
+priest, a little mad, and not a little proud and cruel.
+
+Dunstan was then Abbot of Glastonbury Abbey, whither the body of
+King Edmund the Magnificent was carried, to be buried. While yet a
+boy, he had got out of his bed one night (being then in a fever),
+and walked about Glastonbury Church when it was under repair; and,
+because he did not tumble off some scaffolds that were there, and
+break his neck, it was reported that he had been shown over the
+building by an angel. He had also made a harp that was said to
+play of itself - which it very likely did, as AEolian Harps, which
+are played by the wind, and are understood now, always do. For
+these wonders he had been once denounced by his enemies, who were
+jealous of his favour with the late King Athelstan, as a magician;
+and he had been waylaid, bound hand and foot, and thrown into a
+marsh. But he got out again, somehow, to cause a great deal of
+trouble yet.
+
+The priests of those days were, generally, the only scholars. They
+were learned in many things. Having to make their own convents and
+monasteries on uncultivated grounds that were granted to them by
+the Crown, it was necessary that they should be good farmers and
+good gardeners, or their lands would have been too poor to support
+them. For the decoration of the chapels where they prayed, and for
+the comfort of the refectories where they ate and drank, it was
+necessary that there should be good carpenters, good smiths, good
+painters, among them. For their greater safety in sickness and
+accident, living alone by themselves in solitary places, it was
+necessary that they should study the virtues of plants and herbs,
+and should know how to dress cuts, burns, scalds, and bruises, and
+how to set broken limbs. Accordingly, they taught themselves, and
+one another, a great variety of useful arts; and became skilful in
+agriculture, medicine, surgery, and handicraft. And when they
+wanted the aid of any little piece of machinery, which would be
+simple enough now, but was marvellous then, to impose a trick upon
+the poor peasants, they knew very well how to make it; and DID make
+it many a time and often, I have no doubt.
+
+Dunstan, Abbot of Glastonbury Abbey, was one of the most sagacious
+of these monks. He was an ingenious smith, and worked at a forge
+in a little cell. This cell was made too short to admit of his
+lying at full length when he went to sleep - as if THAT did any
+good to anybody! - and he used to tell the most extraordinary lies
+about demons and spirits, who, he said, came there to persecute
+him. For instance, he related that one day when he was at work,
+the devil looked in at the little window, and tried to tempt him to
+lead a life of idle pleasure; whereupon, having his pincers in the
+fire, red hot, he seized the devil by the nose, and put him to such
+pain, that his bellowings were heard for miles and miles. Some
+people are inclined to think this nonsense a part of Dunstan's
+madness (for his head never quite recovered the fever), but I think
+not. I observe that it induced the ignorant people to consider him
+a holy man, and that it made him very powerful. Which was exactly
+what he always wanted.
+
+On the day of the coronation of the handsome boy-king Edwy, it was
+remarked by ODO, Archbishop of Canterbury (who was a Dane by
+birth), that the King quietly left the coronation feast, while all
+the company were there. Odo, much displeased, sent his friend
+Dunstan to seek him. Dunstan finding him in the company of his
+beautiful young wife ELGIVA, and her mother ETHELGIVA, a good and
+virtuous lady, not only grossly abused them, but dragged the young
+King back into the feasting-hall by force. Some, again, think
+Dunstan did this because the young King's fair wife was his own
+cousin, and the monks objected to people marrying their own
+cousins; but I believe he did it, because he was an imperious,
+audacious, ill-conditioned priest, who, having loved a young lady
+himself before he became a sour monk, hated all love now, and
+everything belonging to it.
+
+The young King was quite old enough to feel this insult. Dunstan
+had been Treasurer in the last reign, and he soon charged Dunstan
+with having taken some of the last king's money. The Glastonbury
+Abbot fled to Belgium (very narrowly escaping some pursuers who
+were sent to put out his eyes, as you will wish they had, when you
+read what follows), and his abbey was given to priests who were
+married; whom he always, both before and afterwards, opposed. But
+he quickly conspired with his friend, Odo the Dane, to set up the
+King's young brother, EDGAR, as his rival for the throne; and, not
+content with this revenge, he caused the beautiful queen Elgiva,
+though a lovely girl of only seventeen or eighteen, to be stolen
+from one of the Royal Palaces, branded in the cheek with a red-hot
+iron, and sold into slavery in Ireland. But the Irish people
+pitied and befriended her; and they said, 'Let us restore the girl-
+queen to the boy-king, and make the young lovers happy!' and they
+cured her of her cruel wound, and sent her home as beautiful as
+before. But the villain Dunstan, and that other villain, Odo,
+caused her to be waylaid at Gloucester as she was joyfully hurrying
+to join her husband, and to be hacked and hewn with swords, and to
+be barbarously maimed and lamed, and left to die. When Edwy the
+Fair (his people called him so, because he was so young and
+handsome) heard of her dreadful fate, he died of a broken heart;
+and so the pitiful story of the poor young wife and husband ends!
+Ah! Better to be two cottagers in these better times, than king
+and queen of England in those bad days, though never so fair!
+
+Then came the boy-king, EDGAR, called the Peaceful, fifteen years
+old. Dunstan, being still the real king, drove all married priests
+out of the monasteries and abbeys, and replaced them by solitary
+monks like himself, of the rigid order called the Benedictines. He
+made himself Archbishop of Canterbury, for his greater glory; and
+exercised such power over the neighbouring British princes, and so
+collected them about the King, that once, when the King held his
+court at Chester, and went on the river Dee to visit the monastery
+of St. John, the eight oars of his boat were pulled (as the people
+used to delight in relating in stories and songs) by eight crowned
+kings, and steered by the King of England. As Edgar was very
+obedient to Dunstan and the monks, they took great pains to
+represent him as the best of kings. But he was really profligate,
+debauched, and vicious. He once forcibly carried off a young lady
+from the convent at Wilton; and Dunstan, pretending to be very much
+shocked, condemned him not to wear his crown upon his head for
+seven years - no great punishment, I dare say, as it can hardly
+have been a more comfortable ornament to wear, than a stewpan
+without a handle. His marriage with his second wife, ELFRIDA, is
+one of the worst events of his reign. Hearing of the beauty of
+this lady, he despatched his favourite courtier, ATHELWOLD, to her
+father's castle in Devonshire, to see if she were really as
+charming as fame reported. Now, she was so exceedingly beautiful
+that Athelwold fell in love with her himself, and married her; but
+he told the King that she was only rich - not handsome. The King,
+suspecting the truth when they came home, resolved to pay the
+newly-married couple a visit; and, suddenly, told Athelwold to
+prepare for his immediate coming. Athelwold, terrified, confessed
+to his young wife what he had said and done, and implored her to
+disguise her beauty by some ugly dress or silly manner, that he
+might be safe from the King's anger. She promised that she would;
+but she was a proud woman, who would far rather have been a queen
+than the wife of a courtier. She dressed herself in her best
+dress, and adorned herself with her richest jewels; and when the
+King came, presently, he discovered the cheat. So, he caused his
+false friend, Athelwold, to be murdered in a wood, and married his
+widow, this bad Elfrida. Six or seven years afterwards, he died;
+and was buried, as if he had been all that the monks said he was,
+in the abbey of Glastonbury, which he - or Dunstan for him - had
+much enriched.
+
+England, in one part of this reign, was so troubled by wolves,
+which, driven out of the open country, hid themselves in the
+mountains of Wales when they were not attacking travellers and
+animals, that the tribute payable by the Welsh people was forgiven
+them, on condition of their producing, every year, three hundred
+wolves' heads. And the Welshmen were so sharp upon the wolves, to
+save their money, that in four years there was not a wolf left.
+
+Then came the boy-king, EDWARD, called the Martyr, from the manner
+of his death. Elfrida had a son, named ETHELRED, for whom she
+claimed the throne; but Dunstan did not choose to favour him, and
+he made Edward king. The boy was hunting, one day, down in
+Dorsetshire, when he rode near to Corfe Castle, where Elfrida and
+Ethelred lived. Wishing to see them kindly, he rode away from his
+attendants and galloped to the castle gate, where he arrived at
+twilight, and blew his hunting-horn. 'You are welcome, dear King,'
+said Elfrida, coming out, with her brightest smiles. 'Pray you
+dismount and enter.' 'Not so, dear madam,' said the King. 'My
+company will miss me, and fear that I have met with some harm.
+Please you to give me a cup of wine, that I may drink here, in the
+saddle, to you and to my little brother, and so ride away with the
+good speed I have made in riding here.' Elfrida, going in to bring
+the wine, whispered an armed servant, one of her attendants, who
+stole out of the darkening gateway, and crept round behind the
+King's horse. As the King raised the cup to his lips, saying,
+'Health!' to the wicked woman who was smiling on him, and to his
+innocent brother whose hand she held in hers, and who was only ten
+years old, this armed man made a spring and stabbed him in the
+back. He dropped the cup and spurred his horse away; but, soon
+fainting with loss of blood, dropped from the saddle, and, in his
+fall, entangled one of his feet in the stirrup. The frightened
+horse dashed on; trailing his rider's curls upon the ground;
+dragging his smooth young face through ruts, and stones, and
+briers, and fallen leaves, and mud; until the hunters, tracking the
+animal's course by the King's blood, caught his bridle, and
+released the disfigured body.
+
+Then came the sixth and last of the boy-kings, ETHELRED, whom
+Elfrida, when he cried out at the sight of his murdered brother
+riding away from the castle gate, unmercifully beat with a torch
+which she snatched from one of the attendants. The people so
+disliked this boy, on account of his cruel mother and the murder
+she had done to promote him, that Dunstan would not have had him
+for king, but would have made EDGITHA, the daughter of the dead
+King Edgar, and of the lady whom he stole out of the convent at
+Wilton, Queen of England, if she would have consented. But she
+knew the stories of the youthful kings too well, and would not be
+persuaded from the convent where she lived in peace; so, Dunstan
+put Ethelred on the throne, having no one else to put there, and
+gave him the nickname of THE UNREADY - knowing that he wanted
+resolution and firmness.
+
+At first, Elfrida possessed great influence over the young King,
+but, as he grew older and came of age, her influence declined. The
+infamous woman, not having it in her power to do any more evil,
+then retired from court, and, according, to the fashion of the
+time, built churches and monasteries, to expiate her guilt. As if
+a church, with a steeple reaching to the very stars, would have
+been any sign of true repentance for the blood of the poor boy,
+whose murdered form was trailed at his horse's heels! As if she
+could have buried her wickedness beneath the senseless stones of
+the whole world, piled up one upon another, for the monks to live
+in!
+
+About the ninth or tenth year of this reign, Dunstan died. He was
+growing old then, but was as stern and artful as ever. Two
+circumstances that happened in connexion with him, in this reign of
+Ethelred, made a great noise. Once, he was present at a meeting of
+the Church, when the question was discussed whether priests should
+have permission to marry; and, as he sat with his head hung down,
+apparently thinking about it, a voice seemed to come out of a
+crucifix in the room, and warn the meeting to be of his opinion.
+This was some juggling of Dunstan's, and was probably his own voice
+disguised. But he played off a worse juggle than that, soon
+afterwards; for, another meeting being held on the same subject,
+and he and his supporters being seated on one side of a great room,
+and their opponents on the other, he rose and said, 'To Christ
+himself, as judge, do I commit this cause!' Immediately on these
+words being spoken, the floor where the opposite party sat gave
+way, and some were killed and many wounded. You may be pretty sure
+that it had been weakened under Dunstan's direction, and that it
+fell at Dunstan's signal. HIS part of the floor did not go down.
+No, no. He was too good a workman for that.
+
+When he died, the monks settled that he was a Saint, and called him
+Saint Dunstan ever afterwards. They might just as well have
+settled that he was a coach-horse, and could just as easily have
+called him one.
+
+Ethelred the Unready was glad enough, I dare say, to be rid of this
+holy saint; but, left to himself, he was a poor weak king, and his
+reign was a reign of defeat and shame. The restless Danes, led by
+SWEYN, a son of the King of Denmark who had quarrelled with his
+father and had been banished from home, again came into England,
+and, year after year, attacked and despoiled large towns. To coax
+these sea-kings away, the weak Ethelred paid them money; but, the
+more money he paid, the more money the Danes wanted. At first, he
+gave them ten thousand pounds; on their next invasion, sixteen
+thousand pounds; on their next invasion, four and twenty thousand
+pounds: to pay which large sums, the unfortunate English people
+were heavily taxed. But, as the Danes still came back and wanted
+more, he thought it would be a good plan to marry into some
+powerful foreign family that would help him with soldiers. So, in
+the year one thousand and two, he courted and married Emma, the
+sister of Richard Duke of Normandy; a lady who was called the
+Flower of Normandy.
+
+And now, a terrible deed was done in England, the like of which was
+never done on English ground before or since. On the thirteenth of
+November, in pursuance of secret instructions sent by the King over
+the whole country, the inhabitants of every town and city armed,
+and murdered all the Danes who were their neighbours.
+
+Young and old, babies and soldiers, men and women, every Dane was
+killed. No doubt there were among them many ferocious men who had
+done the English great wrong, and whose pride and insolence, in
+swaggering in the houses of the English and insulting their wives
+and daughters, had become unbearable; but no doubt there were also
+among them many peaceful Christian Danes who had married English
+women and become like English men. They were all slain, even to
+GUNHILDA, the sister of the King of Denmark, married to an English
+lord; who was first obliged to see the murder of her husband and
+her child, and then was killed herself.
+
+When the King of the sea-kings heard of this deed of blood, he
+swore that he would have a great revenge. He raised an army, and a
+mightier fleet of ships than ever yet had sailed to England; and in
+all his army there was not a slave or an old man, but every soldier
+was a free man, and the son of a free man, and in the prime of
+life, and sworn to be revenged upon the English nation, for the
+massacre of that dread thirteenth of November, when his countrymen
+and countrywomen, and the little children whom they loved, were
+killed with fire and sword. And so, the sea-kings came to England
+in many great ships, each bearing the flag of its own commander.
+Golden eagles, ravens, dragons, dolphins, beasts of prey,
+threatened England from the prows of those ships, as they came
+onward through the water; and were reflected in the shining shields
+that hung upon their sides. The ship that bore the standard of the
+King of the sea-kings was carved and painted like a mighty serpent;
+and the King in his anger prayed that the Gods in whom he trusted
+might all desert him, if his serpent did not strike its fangs into
+England's heart.
+
+And indeed it did. For, the great army landing from the great
+fleet, near Exeter, went forward, laying England waste, and
+striking their lances in the earth as they advanced, or throwing
+them into rivers, in token of their making all the island theirs.
+In remembrance of the black November night when the Danes were
+murdered, wheresoever the invaders came, they made the Saxons
+prepare and spread for them great feasts; and when they had eaten
+those feasts, and had drunk a curse to England with wild
+rejoicings, they drew their swords, and killed their Saxon
+entertainers, and marched on. For six long years they carried on
+this war: burning the crops, farmhouses, barns, mills, granaries;
+killing the labourers in the fields; preventing the seed from being
+sown in the ground; causing famine and starvation; leaving only
+heaps of ruin and smoking ashes, where they had found rich towns.
+To crown this misery, English officers and men deserted, and even
+the favourites of Ethelred the Unready, becoming traitors, seized
+many of the English ships, turned pirates against their own
+country, and aided by a storm occasioned the loss of nearly the
+whole English navy.
+
+There was but one man of note, at this miserable pass, who was true
+to his country and the feeble King. He was a priest, and a brave
+one. For twenty days, the Archbishop of Canterbury defended that
+city against its Danish besiegers; and when a traitor in the town
+threw the gates open and admitted them, he said, in chains, 'I will
+not buy my life with money that must be extorted from the suffering
+people. Do with me what you please!' Again and again, he steadily
+refused to purchase his release with gold wrung from the poor.
+
+At last, the Danes being tired of this, and being assembled at a
+drunken merry-making, had him brought into the feasting-hall.
+
+'Now, bishop,' they said, 'we want gold!'
+
+He looked round on the crowd of angry faces; from the shaggy beards
+close to him, to the shaggy beards against the walls, where men
+were mounted on tables and forms to see him over the heads of
+others: and he knew that his time was come.
+
+'I have no gold,' he said.
+
+'Get it, bishop!' they all thundered.
+
+'That, I have often told you I will not,' said he.
+
+They gathered closer round him, threatening, but he stood unmoved.
+Then, one man struck him; then, another; then a cursing soldier
+picked up from a heap in a corner of the hall, where fragments had
+been rudely thrown at dinner, a great ox-bone, and cast it at his
+face, from which the blood came spurting forth; then, others ran to
+the same heap, and knocked him down with other bones, and bruised
+and battered him; until one soldier whom he had baptised (willing,
+as I hope for the sake of that soldier's soul, to shorten the
+sufferings of the good man) struck him dead with his battle-axe.
+
+If Ethelred had had the heart to emulate the courage of this noble
+archbishop, he might have done something yet. But he paid the
+Danes forty-eight thousand pounds, instead, and gained so little by
+the cowardly act, that Sweyn soon afterwards came over to subdue
+all England. So broken was the attachment of the English people,
+by this time, to their incapable King and their forlorn country
+which could not protect them, that they welcomed Sweyn on all
+sides, as a deliverer. London faithfully stood out, as long as the
+King was within its walls; but, when he sneaked away, it also
+welcomed the Dane. Then, all was over; and the King took refuge
+abroad with the Duke of Normandy, who had already given shelter to
+the King's wife, once the Flower of that country, and to her
+children.
+
+Still, the English people, in spite of their sad sufferings, could
+not quite forget the great King Alfred and the Saxon race. When
+Sweyn died suddenly, in little more than a month after he had been
+proclaimed King of England, they generously sent to Ethelred, to
+say that they would have him for their King again, 'if he would
+only govern them better than he had governed them before.' The
+Unready, instead of coming himself, sent Edward, one of his sons,
+to make promises for him. At last, he followed, and the English
+declared him King. The Danes declared CANUTE, the son of Sweyn,
+King. Thus, direful war began again, and lasted for three years,
+when the Unready died. And I know of nothing better that he did,
+in all his reign of eight and thirty years.
+
+Was Canute to be King now? Not over the Saxons, they said; they
+must have EDMUND, one of the sons of the Unready, who was surnamed
+IRONSIDE, because of his strength and stature. Edmund and Canute
+thereupon fell to, and fought five battles - O unhappy England,
+what a fighting-ground it was! - and then Ironside, who was a big
+man, proposed to Canute, who was a little man, that they two should
+fight it out in single combat. If Canute had been the big man, he
+would probably have said yes, but, being the little man, he
+decidedly said no. However, he declared that he was willing to
+divide the kingdom - to take all that lay north of Watling Street,
+as the old Roman military road from Dover to Chester was called,
+and to give Ironside all that lay south of it. Most men being
+weary of so much bloodshed, this was done. But Canute soon became
+sole King of England; for Ironside died suddenly within two months.
+Some think that he was killed, and killed by Canute's orders. No
+one knows.
+
+
+
+CHAPTER V - ENGLAND UNDER CANUTE THE DANE
+
+
+
+CANUTE reigned eighteen years. He was a merciless King at first.
+After he had clasped the hands of the Saxon chiefs, in token of the
+sincerity with which he swore to be just and good to them in return
+for their acknowledging him, he denounced and slew many of them, as
+well as many relations of the late King. 'He who brings me the
+head of one of my enemies,' he used to say, 'shall be dearer to me
+than a brother.' And he was so severe in hunting down his enemies,
+that he must have got together a pretty large family of these dear
+brothers. He was strongly inclined to kill EDMUND and EDWARD, two
+children, sons of poor Ironside; but, being afraid to do so in
+England, he sent them over to the King of Sweden, with a request
+that the King would be so good as 'dispose of them.' If the King
+of Sweden had been like many, many other men of that day, he would
+have had their innocent throats cut; but he was a kind man, and
+brought them up tenderly.
+
+Normandy ran much in Canute's mind. In Normandy were the two
+children of the late king - EDWARD and ALFRED by name; and their
+uncle the Duke might one day claim the crown for them. But the
+Duke showed so little inclination to do so now, that he proposed to
+Canute to marry his sister, the widow of The Unready; who, being
+but a showy flower, and caring for nothing so much as becoming a
+queen again, left her children and was wedded to him.
+
+Successful and triumphant, assisted by the valour of the English in
+his foreign wars, and with little strife to trouble him at home,
+Canute had a prosperous reign, and made many improvements. He was
+a poet and a musician. He grew sorry, as he grew older, for the
+blood he had shed at first; and went to Rome in a Pilgrim's dress,
+by way of washing it out. He gave a great deal of money to
+foreigners on his journey; but he took it from the English before
+he started. On the whole, however, he certainly became a far
+better man when he had no opposition to contend with, and was as
+great a King as England had known for some time.
+
+The old writers of history relate how that Canute was one day
+disgusted with his courtiers for their flattery, and how he caused
+his chair to be set on the sea-shore, and feigned to command the
+tide as it came up not to wet the edge of his robe, for the land
+was his; how the tide came up, of course, without regarding him;
+and how he then turned to his flatterers, and rebuked them, saying,
+what was the might of any earthly king, to the might of the
+Creator, who could say unto the sea, 'Thus far shalt thou go, and
+no farther!' We may learn from this, I think, that a little sense
+will go a long way in a king; and that courtiers are not easily
+cured of flattery, nor kings of a liking for it. If the courtiers
+of Canute had not known, long before, that the King was fond of
+flattery, they would have known better than to offer it in such
+large doses. And if they had not known that he was vain of this
+speech (anything but a wonderful speech it seems to me, if a good
+child had made it), they would not have been at such great pains to
+repeat it. I fancy I see them all on the sea-shore together; the
+King's chair sinking in the sand; the King in a mighty good humour
+with his own wisdom; and the courtiers pretending to be quite
+stunned by it!
+
+It is not the sea alone that is bidden to go 'thus far, and no
+farther.' The great command goes forth to all the kings upon the
+earth, and went to Canute in the year one thousand and thirty-five,
+and stretched him dead upon his bed. Beside it, stood his Norman
+wife. Perhaps, as the King looked his last upon her, he, who had
+so often thought distrustfully of Normandy, long ago, thought once
+more of the two exiled Princes in their uncle's court, and of the
+little favour they could feel for either Danes or Saxons, and of a
+rising cloud in Normandy that slowly moved towards England.
+
+
+
+CHAPTER VI - ENGLAND UNDER HAROLD HAREFOOT, HARDICANUTE, AND EDWARD
+THE CONFESSOR
+
+
+
+CANUTE left three sons, by name SWEYN, HAROLD, and HARDICANUTE; but
+his Queen, Emma, once the Flower of Normandy, was the mother of
+only Hardicanute. Canute had wished his dominions to be divided
+between the three, and had wished Harold to have England; but the
+Saxon people in the South of England, headed by a nobleman with
+great possessions, called the powerful EARL GODWIN (who is said to
+have been originally a poor cow-boy), opposed this, and desired to
+have, instead, either Hardicanute, or one of the two exiled Princes
+who were over in Normandy. It seemed so certain that there would
+be more bloodshed to settle this dispute, that many people left
+their homes, and took refuge in the woods and swamps. Happily,
+however, it was agreed to refer the whole question to a great
+meeting at Oxford, which decided that Harold should have all the
+country north of the Thames, with London for his capital city, and
+that Hardicanute should have all the south. The quarrel was so
+arranged; and, as Hardicanute was in Denmark troubling himself very
+little about anything but eating and getting drunk, his mother and
+Earl Godwin governed the south for him.
+
+They had hardly begun to do so, and the trembling people who had
+hidden themselves were scarcely at home again, when Edward, the
+elder of the two exiled Princes, came over from Normandy with a few
+followers, to claim the English Crown. His mother Emma, however,
+who only cared for her last son Hardicanute, instead of assisting
+him, as he expected, opposed him so strongly with all her influence
+that he was very soon glad to get safely back. His brother Alfred
+was not so fortunate. Believing in an affectionate letter, written
+some time afterwards to him and his brother, in his mother's name
+(but whether really with or without his mother's knowledge is now
+uncertain), he allowed himself to be tempted over to England, with
+a good force of soldiers, and landing on the Kentish coast, and
+being met and welcomed by Earl Godwin, proceeded into Surrey, as
+far as the town of Guildford. Here, he and his men halted in the
+evening to rest, having still the Earl in their company; who had
+ordered lodgings and good cheer for them. But, in the dead of the
+night, when they were off their guard, being divided into small
+parties sleeping soundly after a long march and a plentiful supper
+in different houses, they were set upon by the King's troops, and
+taken prisoners. Next morning they were drawn out in a line, to
+the number of six hundred men, and were barbarously tortured and
+killed; with the exception of every tenth man, who was sold into
+slavery. As to the wretched Prince Alfred, he was stripped naked,
+tied to a horse and sent away into the Isle of Ely, where his eyes
+were torn out of his head, and where in a few days he miserably
+died. I am not sure that the Earl had wilfully entrapped him, but
+I suspect it strongly.
+
+Harold was now King all over England, though it is doubtful whether
+the Archbishop of Canterbury (the greater part of the priests were
+Saxons, and not friendly to the Danes) ever consented to crown him.
+Crowned or uncrowned, with the Archbishop's leave or without it, he
+was King for four years: after which short reign he died, and was
+buried; having never done much in life but go a hunting. He was
+such a fast runner at this, his favourite sport, that the people
+called him Harold Harefoot.
+
+Hardicanute was then at Bruges, in Flanders, plotting, with his
+mother (who had gone over there after the cruel murder of Prince
+Alfred), for the invasion of England. The Danes and Saxons,
+finding themselves without a King, and dreading new disputes, made
+common cause, and joined in inviting him to occupy the Throne. He
+consented, and soon troubled them enough; for he brought over
+numbers of Danes, and taxed the people so insupportably to enrich
+those greedy favourites that there were many insurrections,
+especially one at Worcester, where the citizens rose and killed his
+tax-collectors; in revenge for which he burned their city. He was
+a brutal King, whose first public act was to order the dead body of
+poor Harold Harefoot to be dug up, beheaded, and thrown into the
+river. His end was worthy of such a beginning. He fell down
+drunk, with a goblet of wine in his hand, at a wedding-feast at
+Lambeth, given in honour of the marriage of his standard-bearer, a
+Dane named TOWED THE PROUD. And he never spoke again.
+
+EDWARD, afterwards called by the monks THE CONFESSOR, succeeded;
+and his first act was to oblige his mother Emma, who had favoured
+him so little, to retire into the country; where she died some ten
+years afterwards. He was the exiled prince whose brother Alfred
+had been so foully killed. He had been invited over from Normandy
+by Hardicanute, in the course of his short reign of two years, and
+had been handsomely treated at court. His cause was now favoured
+by the powerful Earl Godwin, and he was soon made King. This Earl
+had been suspected by the people, ever since Prince Alfred's cruel
+death; he had even been tried in the last reign for the Prince's
+murder, but had been pronounced not guilty; chiefly, as it was
+supposed, because of a present he had made to the swinish King, of
+a gilded ship with a figure-head of solid gold, and a crew of
+eighty splendidly armed men. It was his interest to help the new
+King with his power, if the new King would help him against the
+popular distrust and hatred. So they made a bargain. Edward the
+Confessor got the Throne. The Earl got more power and more land,
+and his daughter Editha was made queen; for it was a part of their
+compact that the King should take her for his wife.
+
+But, although she was a gentle lady, in all things worthy to be
+beloved - good, beautiful, sensible, and kind - the King from the
+first neglected her. Her father and her six proud brothers,
+resenting this cold treatment, harassed the King greatly by
+exerting all their power to make him unpopular. Having lived so
+long in Normandy, he preferred the Normans to the English. He made
+a Norman Archbishop, and Norman Bishops; his great officers and
+favourites were all Normans; he introduced the Norman fashions and
+the Norman language; in imitation of the state custom of Normandy,
+he attached a great seal to his state documents, instead of merely
+marking them, as the Saxon Kings had done, with the sign of the
+cross - just as poor people who have never been taught to write,
+now make the same mark for their names. All this, the powerful
+Earl Godwin and his six proud sons represented to the people as
+disfavour shown towards the English; and thus they daily increased
+their own power, and daily diminished the power of the King.
+
+They were greatly helped by an event that occurred when he had
+reigned eight years. Eustace, Earl of Bologne, who had married the
+King's sister, came to England on a visit. After staying at the
+court some time, he set forth, with his numerous train of
+attendants, to return home. They were to embark at Dover.
+Entering that peaceful town in armour, they took possession of the
+best houses, and noisily demanded to be lodged and entertained
+without payment. One of the bold men of Dover, who would not
+endure to have these domineering strangers jingling their heavy
+swords and iron corselets up and down his house, eating his meat
+and drinking his strong liquor, stood in his doorway and refused
+admission to the first armed man who came there. The armed man
+drew, and wounded him. The man of Dover struck the armed man dead.
+Intelligence of what he had done, spreading through the streets to
+where the Count Eustace and his men were standing by their horses,
+bridle in hand, they passionately mounted, galloped to the house,
+surrounded it, forced their way in (the doors and windows being
+closed when they came up), and killed the man of Dover at his own
+fireside. They then clattered through the streets, cutting down
+and riding over men, women, and children. This did not last long,
+you may believe. The men of Dover set upon them with great fury,
+killed nineteen of the foreigners, wounded many more, and,
+blockading the road to the port so that they should not embark,
+beat them out of the town by the way they had come. Hereupon,
+Count Eustace rides as hard as man can ride to Gloucester, where
+Edward is, surrounded by Norman monks and Norman lords. 'Justice!'
+cries the Count, 'upon the men of Dover, who have set upon and
+slain my people!' The King sends immediately for the powerful Earl
+Godwin, who happens to be near; reminds him that Dover is under his
+government; and orders him to repair to Dover and do military
+execution on the inhabitants. 'It does not become you,' says the
+proud Earl in reply, 'to condemn without a hearing those whom you
+have sworn to protect. I will not do it.'
+
+The King, therefore, summoned the Earl, on pain of banishment and
+loss of his titles and property, to appear before the court to
+answer this disobedience. The Earl refused to appear. He, his
+eldest son Harold, and his second son Sweyn, hastily raised as many
+fighting men as their utmost power could collect, and demanded to
+have Count Eustace and his followers surrendered to the justice of
+the country. The King, in his turn, refused to give them up, and
+raised a strong force. After some treaty and delay, the troops of
+the great Earl and his sons began to fall off. The Earl, with a
+part of his family and abundance of treasure, sailed to Flanders;
+Harold escaped to Ireland; and the power of the great family was
+for that time gone in England. But, the people did not forget
+them.
+
+Then, Edward the Confessor, with the true meanness of a mean
+spirit, visited his dislike of the once powerful father and sons
+upon the helpless daughter and sister, his unoffending wife, whom
+all who saw her (her husband and his monks excepted) loved. He
+seized rapaciously upon her fortune and her jewels, and allowing
+her only one attendant, confined her in a gloomy convent, of which
+a sister of his - no doubt an unpleasant lady after his own heart -
+was abbess or jailer.
+
+Having got Earl Godwin and his six sons well out of his way, the
+King favoured the Normans more than ever. He invited over WILLIAM,
+DUKE OF NORMANDY, the son of that Duke who had received him and his
+murdered brother long ago, and of a peasant girl, a tanner's
+daughter, with whom that Duke had fallen in love for her beauty as
+he saw her washing clothes in a brook. William, who was a great
+warrior, with a passion for fine horses, dogs, and arms, accepted
+the invitation; and the Normans in England, finding themselves more
+numerous than ever when he arrived with his retinue, and held in
+still greater honour at court than before, became more and more
+haughty towards the people, and were more and more disliked by
+them.
+
+The old Earl Godwin, though he was abroad, knew well how the people
+felt; for, with part of the treasure he had carried away with him,
+he kept spies and agents in his pay all over England.
+
+Accordingly, he thought the time was come for fitting out a great
+expedition against the Norman-loving King. With it, he sailed to
+the Isle of Wight, where he was joined by his son Harold, the most
+gallant and brave of all his family. And so the father and son
+came sailing up the Thames to Southwark; great numbers of the
+people declaring for them, and shouting for the English Earl and
+the English Harold, against the Norman favourites!
+
+The King was at first as blind and stubborn as kings usually have
+been whensoever they have been in the hands of monks. But the
+people rallied so thickly round the old Earl and his son, and the
+old Earl was so steady in demanding without bloodshed the
+restoration of himself and his family to their rights, that at last
+the court took the alarm. The Norman Archbishop of Canterbury, and
+the Norman Bishop of London, surrounded by their retainers, fought
+their way out of London, and escaped from Essex to France in a
+fishing-boat. The other Norman favourites dispersed in all
+directions. The old Earl and his sons (except Sweyn, who had
+committed crimes against the law) were restored to their
+possessions and dignities. Editha, the virtuous and lovely Queen
+of the insensible King, was triumphantly released from her prison,
+the convent, and once more sat in her chair of state, arrayed in
+the jewels of which, when she had no champion to support her
+rights, her cold-blooded husband had deprived her.
+
+The old Earl Godwin did not long enjoy his restored fortune. He
+fell down in a fit at the King's table, and died upon the third day
+afterwards. Harold succeeded to his power, and to a far higher
+place in the attachment of the people than his father had ever
+held. By his valour he subdued the King's enemies in many bloody
+fights. He was vigorous against rebels in Scotland - this was the
+time when Macbeth slew Duncan, upon which event our English
+Shakespeare, hundreds of years afterwards, wrote his great tragedy;
+and he killed the restless Welsh King GRIFFITH, and brought his
+head to England.
+
+What Harold was doing at sea, when he was driven on the French
+coast by a tempest, is not at all certain; nor does it at all
+matter. That his ship was forced by a storm on that shore, and
+that he was taken prisoner, there is no doubt. In those barbarous
+days, all shipwrecked strangers were taken prisoners, and obliged
+to pay ransom. So, a certain Count Guy, who was the Lord of
+Ponthieu where Harold's disaster happened, seized him, instead of
+relieving him like a hospitable and Christian lord as he ought to
+have done, and expected to make a very good thing of it.
+
+But Harold sent off immediately to Duke William of Normandy,
+complaining of this treatment; and the Duke no sooner heard of it
+than he ordered Harold to be escorted to the ancient town of Rouen,
+where he then was, and where he received him as an honoured guest.
+Now, some writers tell us that Edward the Confessor, who was by
+this time old and had no children, had made a will, appointing Duke
+William of Normandy his successor, and had informed the Duke of his
+having done so. There is no doubt that he was anxious about his
+successor; because he had even invited over, from abroad, EDWARD
+THE OUTLAW, a son of Ironside, who had come to England with his
+wife and three children, but whom the King had strangely refused to
+see when he did come, and who had died in London suddenly (princes
+were terribly liable to sudden death in those days), and had been
+buried in St. Paul's Cathedral. The King might possibly have made
+such a will; or, having always been fond of the Normans, he might
+have encouraged Norman William to aspire to
\ No newline at end of file
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zlib.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zlib.go
new file mode 100644
index 00000000..76457c6b
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zlib.go
@@ -0,0 +1,81 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package compression
+
+import (
+ "bytes"
+ "compress/zlib"
+ "io"
+)
+
+type zlibProvider struct{}
+
+// NewZLibProvider returns a Provider interface
+func NewZLibProvider() Provider {
+ return &zlibProvider{}
+}
+
+func (zlibProvider) CompressMaxSize(originalSize int) int {
+ // Use formula from ZLib: https://github.com/madler/zlib/blob/cacf7f1d4e3d44d871b605da3b647f07d718623f/deflate.c#L659
+ return originalSize +
+ ((originalSize + 7) >> 3) + ((originalSize + 63) >> 6) + 11
+}
+
+func (zlibProvider) Compress(dst, src []byte) []byte {
+ var b = bytes.NewBuffer(dst[:0])
+ w := zlib.NewWriter(b)
+
+ if _, err := w.Write(src); err != nil {
+ return nil
+ }
+ if err := w.Close(); err != nil {
+ return nil
+ }
+
+ return b.Bytes()
+}
+
+func (zlibProvider) Decompress(dst, src []byte, originalSize int) ([]byte, error) {
+ r, err := zlib.NewReader(bytes.NewReader(src))
+ if err != nil {
+ return nil, err
+ }
+
+ if cap(dst) >= originalSize {
+ dst = dst[0:originalSize] // Reuse dst buffer
+ } else {
+ dst = make([]byte, originalSize)
+ }
+ if _, err = io.ReadFull(r, dst); err != nil {
+ return nil, err
+ }
+
+ if err = r.Close(); err != nil {
+ return nil, err
+ }
+
+ return dst, nil
+}
+
+func (zlibProvider) Clone() Provider {
+ return NewZLibProvider()
+}
+
+func (zlibProvider) Close() error {
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd.go
new file mode 100644
index 00000000..5142e0f5
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd.go
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build !cgo
+// +build !cgo
+
+package compression
+
+import (
+ "fmt"
+)
+
+func NewZStdProvider(level Level) Provider {
+ return newPureGoZStdProvider(level)
+}
+
+func newCGoZStdProvider(level Level) Provider {
+ // This is kept to avoid compile errors in benchmark code when cgo is disabled.
+ // The warning is only shown when running the benchmark with CGO disabled.
+ fmt.Println("WARNING: CGO is disabled, using pure Go implementation of ZStd. Use CGO_ENABLED=1 when running benchmark.")
+ return newPureGoZStdProvider(level)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd_cgo.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd_cgo.go
new file mode 100644
index 00000000..25429e25
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd_cgo.go
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build cgo
+// +build cgo
+
+// If CGO is enabled, use ZSTD library that links with official
+// C based zstd which provides better performance compared with
+// respect to the native Go implementation of ZStd.
+
+package compression
+
+import (
+ "github.com/DataDog/zstd"
+ log "github.com/sirupsen/logrus"
+)
+
+type zstdCGoProvider struct {
+ ctx zstd.Ctx
+ level Level
+ zstdLevel int
+}
+
+func newCGoZStdProvider(level Level) Provider {
+ z := &zstdCGoProvider{
+ ctx: zstd.NewCtx(),
+ }
+
+ switch level {
+ case Default:
+ z.zstdLevel = zstd.DefaultCompression
+ case Faster:
+ z.zstdLevel = zstd.BestSpeed
+ case Better:
+ z.zstdLevel = 9
+ }
+
+ return z
+}
+
+func NewZStdProvider(level Level) Provider {
+ return newCGoZStdProvider(level)
+}
+
+func (z *zstdCGoProvider) CompressMaxSize(originalSize int) int {
+ return zstd.CompressBound(originalSize)
+}
+
+func (z *zstdCGoProvider) Compress(dst, src []byte) []byte {
+ out, err := z.ctx.CompressLevel(dst, src, z.zstdLevel)
+ if err != nil {
+ log.WithError(err).Fatal("Failed to compress")
+ }
+
+ return out
+}
+
+func (z *zstdCGoProvider) Decompress(dst, src []byte, originalSize int) ([]byte, error) {
+ return z.ctx.Decompress(dst, src)
+}
+
+func (z *zstdCGoProvider) Close() error {
+ return nil
+}
+
+func (z *zstdCGoProvider) Clone() Provider {
+ return newCGoZStdProvider(z.level)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd_go.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd_go.go
new file mode 100644
index 00000000..ae850783
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/compression/zstd_go.go
@@ -0,0 +1,72 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package compression
+
+import (
+ "github.com/klauspost/compress/zstd"
+)
+
+type zstdProvider struct {
+ compressionLevel Level
+ encoder *zstd.Encoder
+ decoder *zstd.Decoder
+}
+
+func newPureGoZStdProvider(level Level) Provider {
+ var zstdLevel zstd.EncoderLevel
+ p := &zstdProvider{}
+ switch level {
+ case Default:
+ zstdLevel = zstd.SpeedDefault
+ case Faster:
+ zstdLevel = zstd.SpeedFastest
+ case Better:
+ zstdLevel = zstd.SpeedBetterCompression
+ }
+ p.encoder, _ = zstd.NewWriter(nil, zstd.WithEncoderLevel(zstdLevel))
+ p.decoder, _ = zstd.NewReader(nil)
+ return p
+}
+
+func (p *zstdProvider) CompressMaxSize(srcSize int) int {
+ // from zstd.h
+ // this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB
+ lowLimit := 128 << 10 // 128 kB
+ var margin int
+ if srcSize < lowLimit {
+ margin = (lowLimit - srcSize) >> 11
+ }
+ return srcSize + (srcSize >> 8) + margin
+}
+
+func (p *zstdProvider) Compress(dst, src []byte) []byte {
+ return p.encoder.EncodeAll(src, dst)
+}
+
+func (p *zstdProvider) Decompress(dst, src []byte, originalSize int) ([]byte, error) {
+ return p.decoder.DecodeAll(src, dst)
+}
+
+func (p *zstdProvider) Close() error {
+ p.decoder.Close()
+ return p.encoder.Close()
+}
+
+func (p *zstdProvider) Clone() Provider {
+ return newPureGoZStdProvider(p.compressionLevel)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection.go
new file mode 100644
index 00000000..59aad167
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection.go
@@ -0,0 +1,1125 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "os"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/auth"
+
+ "google.golang.org/protobuf/proto"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+
+ ua "go.uber.org/atomic"
+)
+
+const (
+ PulsarProtocolVersion = int32(pb.ProtocolVersion_v18)
+)
+
+type TLSOptions struct {
+ KeyFile string
+ CertFile string
+ TrustCertsFilePath string
+ AllowInsecureConnection bool
+ ValidateHostname bool
+ ServerName string
+}
+
+var (
+ errConnectionClosed = errors.New("connection closed")
+ errUnableRegisterListener = errors.New("unable register listener when con closed")
+ errUnableAddConsumeHandler = errors.New("unable add consumer handler when con closed")
+)
+
+// ConnectionListener is a user of a connection (eg. a producer or
+// a consumer) that can register itself to get notified
+// when the connection is closed.
+type ConnectionListener interface {
+ // ReceivedSendReceipt receive and process the return value of the send command.
+ ReceivedSendReceipt(response *pb.CommandSendReceipt)
+
+ // ConnectionClosed close the TCP connection.
+ ConnectionClosed()
+}
+
+// Connection is a interface of client cnx.
+type Connection interface {
+ SendRequest(requestID uint64, req *pb.BaseCommand, callback func(*pb.BaseCommand, error))
+ SendRequestNoWait(req *pb.BaseCommand) error
+ WriteData(data Buffer)
+ RegisterListener(id uint64, listener ConnectionListener) error
+ UnregisterListener(id uint64)
+ AddConsumeHandler(id uint64, handler ConsumerHandler) error
+ DeleteConsumeHandler(id uint64)
+ ID() string
+ GetMaxMessageSize() int32
+ Close()
+}
+
+type ConsumerHandler interface {
+ MessageReceived(response *pb.CommandMessage, headersAndPayload Buffer) error
+
+ ActiveConsumerChanged(isActive bool)
+
+ // ConnectionClosed close the TCP connection.
+ ConnectionClosed()
+}
+
+type connectionState int32
+
+const (
+ connectionInit = iota
+ connectionReady
+ connectionClosing
+ connectionClosed
+)
+
+func (s connectionState) String() string {
+ switch s {
+ case connectionInit:
+ return "Initializing"
+ case connectionReady:
+ return "Ready"
+ case connectionClosing:
+ return "Closing"
+ case connectionClosed:
+ return "Closed"
+ default:
+ return "Unknown"
+ }
+}
+
+type request struct {
+ id *uint64
+ cmd *pb.BaseCommand
+ callback func(command *pb.BaseCommand, err error)
+}
+
+type incomingCmd struct {
+ cmd *pb.BaseCommand
+ headersAndPayload Buffer
+}
+
+type connection struct {
+ sync.Mutex
+ cond *sync.Cond
+ started int32
+ state ua.Int32
+ connectionTimeout time.Duration
+ closeOnce sync.Once
+
+ logicalAddr *url.URL
+ physicalAddr *url.URL
+ cnx net.Conn
+
+ writeBufferLock sync.Mutex
+ writeBuffer Buffer
+ reader *connectionReader
+
+ lastDataReceivedLock sync.Mutex
+ lastDataReceivedTime time.Time
+
+ log log.Logger
+
+ incomingRequestsWG sync.WaitGroup
+ incomingRequestsCh chan *request
+ incomingCmdCh chan *incomingCmd
+ closeCh chan interface{}
+ writeRequestsCh chan Buffer
+
+ pendingLock sync.Mutex
+ pendingReqs map[uint64]*request
+
+ listenersLock sync.RWMutex
+ listeners map[uint64]ConnectionListener
+
+ consumerHandlersLock sync.RWMutex
+ consumerHandlers map[uint64]ConsumerHandler
+
+ tlsOptions *TLSOptions
+ auth auth.Provider
+
+ maxMessageSize int32
+ metrics *Metrics
+
+ keepAliveInterval time.Duration
+
+ lastActive time.Time
+}
+
+// connectionOptions defines configurations for creating connection.
+type connectionOptions struct {
+ logicalAddr *url.URL
+ physicalAddr *url.URL
+ tls *TLSOptions
+ connectionTimeout time.Duration
+ auth auth.Provider
+ logger log.Logger
+ metrics *Metrics
+ keepAliveInterval time.Duration
+}
+
+func newConnection(opts connectionOptions) *connection {
+ cnx := &connection{
+ connectionTimeout: opts.connectionTimeout,
+ keepAliveInterval: opts.keepAliveInterval,
+ logicalAddr: opts.logicalAddr,
+ physicalAddr: opts.physicalAddr,
+ writeBuffer: NewBuffer(4096),
+ log: opts.logger.SubLogger(log.Fields{"remote_addr": opts.physicalAddr}),
+ pendingReqs: make(map[uint64]*request),
+ lastDataReceivedTime: time.Now(),
+ tlsOptions: opts.tls,
+ auth: opts.auth,
+
+ closeCh: make(chan interface{}),
+ incomingRequestsCh: make(chan *request, 10),
+ incomingCmdCh: make(chan *incomingCmd, 10),
+
+ // This channel is used to pass data from producers to the connection
+ // go routine. It can become contended or blocking if we have multiple
+ // partition produces writing on a single connection. In general it's
+ // good to keep this above the number of partition producers assigned
+ // to a single connection.
+ writeRequestsCh: make(chan Buffer, 256),
+ listeners: make(map[uint64]ConnectionListener),
+ consumerHandlers: make(map[uint64]ConsumerHandler),
+ metrics: opts.metrics,
+ }
+ cnx.setState(connectionInit)
+ cnx.reader = newConnectionReader(cnx)
+ cnx.cond = sync.NewCond(cnx)
+ return cnx
+}
+
+func (c *connection) start() {
+ if !atomic.CompareAndSwapInt32(&c.started, 0, 1) {
+ c.log.Warnf("connection has already started")
+ return
+ }
+
+ // Each connection gets its own goroutine that will
+ go func() {
+ if c.connect() {
+ if c.doHandshake() {
+ c.metrics.ConnectionsOpened.Inc()
+ c.run()
+ } else {
+ c.metrics.ConnectionsHandshakeErrors.Inc()
+ c.Close()
+ }
+ } else {
+ c.metrics.ConnectionsEstablishmentErrors.Inc()
+ c.Close()
+ }
+ }()
+}
+
+func (c *connection) connect() bool {
+ c.log.Info("Connecting to broker")
+
+ var (
+ err error
+ cnx net.Conn
+ tlsConfig *tls.Config
+ )
+
+ if c.tlsOptions == nil {
+ // Clear text connection
+ cnx, err = net.DialTimeout("tcp", c.physicalAddr.Host, c.connectionTimeout)
+ } else {
+ // TLS connection
+ tlsConfig, err = c.getTLSConfig()
+ if err != nil {
+ c.log.WithError(err).Warn("Failed to configure TLS ")
+ return false
+ }
+
+ d := &net.Dialer{Timeout: c.connectionTimeout}
+ cnx, err = tls.DialWithDialer(d, "tcp", c.physicalAddr.Host, tlsConfig)
+ }
+
+ if err != nil {
+ c.log.WithError(err).Warn("Failed to connect to broker.")
+ c.Close()
+ return false
+ }
+
+ c.Lock()
+ c.cnx = cnx
+ c.log = c.log.SubLogger(log.Fields{"local_addr": c.cnx.LocalAddr()})
+ c.log.Info("TCP connection established")
+ c.Unlock()
+
+ return true
+}
+
+func (c *connection) doHandshake() bool {
+ // Send 'Connect' command to initiate handshake
+ authData, err := c.auth.GetData()
+ if err != nil {
+ c.log.WithError(err).Warn("Failed to load auth credentials")
+ return false
+ }
+
+ // During the initial handshake, the internal keep alive is not
+ // active yet, so we need to timeout write and read requests
+ c.cnx.SetDeadline(time.Now().Add(c.keepAliveInterval))
+ cmdConnect := &pb.CommandConnect{
+ ProtocolVersion: proto.Int32(PulsarProtocolVersion),
+ ClientVersion: proto.String(ClientVersionString),
+ AuthMethodName: proto.String(c.auth.Name()),
+ AuthData: authData,
+ FeatureFlags: &pb.FeatureFlags{
+ SupportsAuthRefresh: proto.Bool(true),
+ SupportsBrokerEntryMetadata: proto.Bool(true),
+ },
+ }
+
+ if c.logicalAddr.Host != c.physicalAddr.Host {
+ cmdConnect.ProxyToBrokerUrl = proto.String(c.logicalAddr.Host)
+ }
+ c.writeCommand(baseCommand(pb.BaseCommand_CONNECT, cmdConnect))
+ cmd, _, err := c.reader.readSingleCommand()
+ if err != nil {
+ c.log.WithError(err).Warn("Failed to perform initial handshake")
+ return false
+ }
+
+ // Reset the deadline so that we don't use read timeouts
+ c.cnx.SetDeadline(time.Time{})
+
+ if cmd.Connected == nil {
+ c.log.Warnf("Failed to establish connection with broker: '%s'",
+ cmd.Error.GetMessage())
+ return false
+ }
+ if cmd.Connected.MaxMessageSize != nil && *cmd.Connected.MaxMessageSize > 0 {
+ c.log.Debug("Got MaxMessageSize from handshake response:", *cmd.Connected.MaxMessageSize)
+ c.maxMessageSize = *cmd.Connected.MaxMessageSize
+ } else {
+ c.log.Debug("No MaxMessageSize from handshake response, use default: ", MaxMessageSize)
+ c.maxMessageSize = MaxMessageSize
+ }
+ c.log.Info("Connection is ready")
+ c.changeState(connectionReady)
+ return true
+}
+
+func (c *connection) waitUntilReady() error {
+ // If we are going to call cond.Wait() at all, then we must call it _before_ we call cond.Broadcast().
+ // The lock is held here to prevent changeState() from calling cond.Broadcast() in the time between
+ // the state check and call to cond.Wait().
+ c.Lock()
+ defer c.Unlock()
+
+ for c.getState() != connectionReady {
+ c.log.Debugf("Wait until connection is ready state=%s", c.getState().String())
+ if c.getState() == connectionClosed {
+ return errors.New("connection error")
+ }
+ // wait for a new connection state change
+ c.cond.Wait()
+ }
+
+ return nil
+}
+
+func (c *connection) failLeftRequestsWhenClose() {
+ // wait for outstanding incoming requests to complete before draining
+ // and closing the channel
+ c.incomingRequestsWG.Wait()
+
+ ch := c.incomingRequestsCh
+ go func() {
+ // send a nil message to drain instead of
+ // closing the channel and causing a potential panic
+ //
+ // if other requests come in after the nil message
+ // then the RPC client will time out
+ ch <- nil
+ }()
+ for req := range ch {
+ if nil == req {
+ break // we have drained the requests
+ }
+ c.internalSendRequest(req)
+ }
+}
+
+func (c *connection) run() {
+ pingSendTicker := time.NewTicker(c.keepAliveInterval)
+ pingCheckTicker := time.NewTicker(c.keepAliveInterval)
+
+ defer func() {
+ // stop tickers
+ pingSendTicker.Stop()
+ pingCheckTicker.Stop()
+
+ // all the accesses to the pendingReqs should be happened in this run loop thread,
+ // including the final cleanup, to avoid the issue
+ // https://github.com/apache/pulsar-client-go/issues/239
+ c.failPendingRequests(errConnectionClosed)
+ c.Close()
+ }()
+
+ // All reads come from the reader goroutine
+ go c.reader.readFromConnection()
+ go c.runPingCheck(pingCheckTicker)
+
+ c.log.Debugf("Connection run starting with request capacity=%d queued=%d",
+ cap(c.incomingRequestsCh), len(c.incomingRequestsCh))
+
+ go func() {
+ for {
+ select {
+ case <-c.closeCh:
+ c.failLeftRequestsWhenClose()
+ return
+
+ case req := <-c.incomingRequestsCh:
+ if req == nil {
+ return // TODO: this never gonna be happen
+ }
+ c.internalSendRequest(req)
+ }
+ }
+ }()
+
+ for {
+ select {
+ case <-c.closeCh:
+ return
+
+ case cmd := <-c.incomingCmdCh:
+ c.internalReceivedCommand(cmd.cmd, cmd.headersAndPayload)
+ case data := <-c.writeRequestsCh:
+ if data == nil {
+ return
+ }
+ c.internalWriteData(data)
+
+ case <-pingSendTicker.C:
+ c.sendPing()
+ }
+ }
+}
+
+func (c *connection) runPingCheck(pingCheckTicker *time.Ticker) {
+ for {
+ select {
+ case <-c.closeCh:
+ return
+ case <-pingCheckTicker.C:
+ if c.lastDataReceived().Add(2 * c.keepAliveInterval).Before(time.Now()) {
+ // We have not received a response to the previous Ping request, the
+ // connection to broker is stale
+ c.log.Warn("Detected stale connection to broker")
+ c.Close()
+ return
+ }
+ }
+ }
+}
+
+func (c *connection) WriteData(data Buffer) {
+ select {
+ case c.writeRequestsCh <- data:
+ // Channel is not full
+ return
+
+ default:
+ // Channel full, fallback to probe if connection is closed
+ }
+
+ for {
+ select {
+ case c.writeRequestsCh <- data:
+ // Successfully wrote on the channel
+ return
+
+ case <-time.After(100 * time.Millisecond):
+ // The channel is either:
+ // 1. blocked, in which case we need to wait until we have space
+ // 2. the connection is already closed, then we need to bail out
+ c.log.Debug("Couldn't write on connection channel immediately")
+ state := c.getState()
+ if state != connectionReady {
+ c.log.Debug("Connection was already closed")
+ return
+ }
+ }
+ }
+
+}
+
+func (c *connection) internalWriteData(data Buffer) {
+ c.log.Debug("Write data: ", data.ReadableBytes())
+ if _, err := c.cnx.Write(data.ReadableSlice()); err != nil {
+ c.log.WithError(err).Warn("Failed to write on connection")
+ c.Close()
+ }
+}
+
+func (c *connection) writeCommand(cmd *pb.BaseCommand) {
+ // Wire format
+ // [FRAME_SIZE] [CMD_SIZE][CMD]
+ cmdSize := uint32(proto.Size(cmd))
+ frameSize := cmdSize + 4
+
+ c.writeBufferLock.Lock()
+ defer c.writeBufferLock.Unlock()
+
+ c.writeBuffer.Clear()
+ c.writeBuffer.WriteUint32(frameSize)
+
+ c.writeBuffer.WriteUint32(cmdSize)
+ c.writeBuffer.ResizeIfNeeded(cmdSize)
+ err := MarshalToSizedBuffer(cmd, c.writeBuffer.WritableSlice()[:cmdSize])
+ if err != nil {
+ c.log.WithError(err).Error("Protobuf serialization error")
+ panic("Protobuf serialization error")
+ }
+
+ c.writeBuffer.WrittenBytes(cmdSize)
+ c.internalWriteData(c.writeBuffer)
+}
+
+func (c *connection) receivedCommand(cmd *pb.BaseCommand, headersAndPayload Buffer) {
+ c.incomingCmdCh <- &incomingCmd{cmd, headersAndPayload}
+}
+
+func (c *connection) internalReceivedCommand(cmd *pb.BaseCommand, headersAndPayload Buffer) {
+ c.log.Debugf("Received command: %s -- payload: %v", cmd, headersAndPayload)
+ c.setLastDataReceived(time.Now())
+
+ switch *cmd.Type {
+ case pb.BaseCommand_SUCCESS:
+ c.handleResponse(cmd.Success.GetRequestId(), cmd)
+
+ case pb.BaseCommand_PRODUCER_SUCCESS:
+ if !cmd.ProducerSuccess.GetProducerReady() {
+ request, ok := c.findPendingRequest(cmd.ProducerSuccess.GetRequestId())
+ if ok {
+ request.callback(cmd, nil)
+ }
+ } else {
+ c.handleResponse(cmd.ProducerSuccess.GetRequestId(), cmd)
+ }
+ case pb.BaseCommand_PARTITIONED_METADATA_RESPONSE:
+ c.checkServerError(cmd.PartitionMetadataResponse.Error)
+ c.handleResponse(cmd.PartitionMetadataResponse.GetRequestId(), cmd)
+
+ case pb.BaseCommand_LOOKUP_RESPONSE:
+ lookupResult := cmd.LookupTopicResponse
+ c.checkServerError(lookupResult.Error)
+ c.handleResponse(lookupResult.GetRequestId(), cmd)
+
+ case pb.BaseCommand_CONSUMER_STATS_RESPONSE:
+ c.handleResponse(cmd.ConsumerStatsResponse.GetRequestId(), cmd)
+
+ case pb.BaseCommand_GET_LAST_MESSAGE_ID_RESPONSE:
+ c.handleResponse(cmd.GetLastMessageIdResponse.GetRequestId(), cmd)
+
+ case pb.BaseCommand_GET_TOPICS_OF_NAMESPACE_RESPONSE:
+ c.handleResponse(cmd.GetTopicsOfNamespaceResponse.GetRequestId(), cmd)
+
+ case pb.BaseCommand_GET_SCHEMA_RESPONSE:
+ c.handleResponse(cmd.GetSchemaResponse.GetRequestId(), cmd)
+
+ case pb.BaseCommand_GET_OR_CREATE_SCHEMA_RESPONSE:
+ c.handleResponse(cmd.GetOrCreateSchemaResponse.GetRequestId(), cmd)
+
+ case pb.BaseCommand_ERROR:
+ c.handleResponseError(cmd.GetError())
+
+ case pb.BaseCommand_SEND_ERROR:
+ c.handleSendError(cmd.GetSendError())
+
+ case pb.BaseCommand_CLOSE_PRODUCER:
+ c.handleCloseProducer(cmd.GetCloseProducer())
+
+ case pb.BaseCommand_CLOSE_CONSUMER:
+ c.handleCloseConsumer(cmd.GetCloseConsumer())
+
+ case pb.BaseCommand_AUTH_CHALLENGE:
+ c.handleAuthChallenge(cmd.GetAuthChallenge())
+
+ case pb.BaseCommand_SEND_RECEIPT:
+ c.handleSendReceipt(cmd.GetSendReceipt())
+
+ case pb.BaseCommand_MESSAGE:
+ c.handleMessage(cmd.GetMessage(), headersAndPayload)
+
+ case pb.BaseCommand_ACK_RESPONSE:
+ c.handleAckResponse(cmd.GetAckResponse())
+
+ case pb.BaseCommand_PING:
+ c.handlePing()
+ case pb.BaseCommand_PONG:
+ c.handlePong()
+ case pb.BaseCommand_TC_CLIENT_CONNECT_RESPONSE:
+ c.handleResponse(cmd.TcClientConnectResponse.GetRequestId(), cmd)
+ case pb.BaseCommand_NEW_TXN_RESPONSE:
+ c.handleResponse(cmd.NewTxnResponse.GetRequestId(), cmd)
+ case pb.BaseCommand_ADD_PARTITION_TO_TXN_RESPONSE:
+ c.handleResponse(cmd.AddPartitionToTxnResponse.GetRequestId(), cmd)
+ case pb.BaseCommand_ADD_SUBSCRIPTION_TO_TXN_RESPONSE:
+ c.handleResponse(cmd.AddSubscriptionToTxnResponse.GetRequestId(), cmd)
+ case pb.BaseCommand_END_TXN_RESPONSE:
+ c.handleResponse(cmd.EndTxnResponse.GetRequestId(), cmd)
+ case pb.BaseCommand_ACTIVE_CONSUMER_CHANGE:
+ c.handleActiveConsumerChange(cmd.GetActiveConsumerChange())
+
+ default:
+ c.log.Errorf("Received invalid command type: %s", cmd.Type)
+ c.Close()
+ }
+}
+
+func (c *connection) checkServerError(err *pb.ServerError) {
+ if err == nil {
+ return
+ }
+
+ if *err == pb.ServerError_ServiceNotReady {
+ c.Close()
+ }
+}
+
+func (c *connection) Write(data Buffer) {
+ c.writeRequestsCh <- data
+}
+
+func (c *connection) SendRequest(requestID uint64, req *pb.BaseCommand,
+ callback func(command *pb.BaseCommand, err error)) {
+ c.incomingRequestsWG.Add(1)
+ defer c.incomingRequestsWG.Done()
+
+ state := c.getState()
+ if state == connectionClosed || state == connectionClosing {
+ callback(req, ErrConnectionClosed)
+
+ } else {
+ select {
+ case <-c.closeCh:
+ callback(req, ErrConnectionClosed)
+
+ case c.incomingRequestsCh <- &request{
+ id: &requestID,
+ cmd: req,
+ callback: callback,
+ }:
+ }
+ }
+}
+
+func (c *connection) SendRequestNoWait(req *pb.BaseCommand) error {
+ c.incomingRequestsWG.Add(1)
+ defer c.incomingRequestsWG.Done()
+
+ state := c.getState()
+ if state == connectionClosed || state == connectionClosing {
+ return ErrConnectionClosed
+ }
+
+ select {
+ case <-c.closeCh:
+ return ErrConnectionClosed
+
+ case c.incomingRequestsCh <- &request{
+ id: nil,
+ cmd: req,
+ callback: nil,
+ }:
+ return nil
+ }
+}
+
+func (c *connection) internalSendRequest(req *request) {
+ if c.closed() {
+ c.log.Warnf("internalSendRequest failed for connectionClosed")
+ if req.callback != nil {
+ req.callback(req.cmd, ErrConnectionClosed)
+ }
+ } else {
+ c.pendingLock.Lock()
+ if req.id != nil {
+ c.pendingReqs[*req.id] = req
+ }
+ c.pendingLock.Unlock()
+ c.writeCommand(req.cmd)
+ }
+}
+
+func (c *connection) handleResponse(requestID uint64, response *pb.BaseCommand) {
+ request, ok := c.deletePendingRequest(requestID)
+ if !ok {
+ c.log.Warnf("Received unexpected response for request %d of type %s", requestID, response.Type)
+ return
+ }
+
+ request.callback(response, nil)
+}
+
+func (c *connection) handleResponseError(serverError *pb.CommandError) {
+ requestID := serverError.GetRequestId()
+
+ request, ok := c.deletePendingRequest(requestID)
+ if !ok {
+ c.log.Warnf("Received unexpected error response for request %d of type %s",
+ requestID, serverError.GetError())
+ return
+ }
+
+ errMsg := fmt.Sprintf("server error: %s: %s", serverError.GetError(), serverError.GetMessage())
+ request.callback(nil, errors.New(errMsg))
+}
+
+func (c *connection) handleAckResponse(ackResponse *pb.CommandAckResponse) {
+ requestID := ackResponse.GetRequestId()
+ consumerID := ackResponse.GetConsumerId()
+
+ request, ok := c.deletePendingRequest(requestID)
+ if !ok {
+ c.log.Warnf("AckResponse has complete when receive response! requestId : %d, consumerId : %d",
+ requestID, consumerID)
+ return
+ }
+
+ if ackResponse.GetMessage() == "" {
+ request.callback(nil, nil)
+ return
+ }
+
+ errMsg := fmt.Sprintf("ack response error: %s: %s", ackResponse.GetError(), ackResponse.GetMessage())
+ request.callback(nil, errors.New(errMsg))
+}
+
+func (c *connection) handleSendReceipt(response *pb.CommandSendReceipt) {
+ producerID := response.GetProducerId()
+
+ c.listenersLock.RLock()
+ producer, ok := c.listeners[producerID]
+ c.listenersLock.RUnlock()
+
+ if ok {
+ producer.ReceivedSendReceipt(response)
+ } else {
+ c.log.
+ WithField("producerID", producerID).
+ Warn("Got unexpected send receipt for messageID=%+v", response.MessageId)
+ }
+}
+
+func (c *connection) handleMessage(response *pb.CommandMessage, payload Buffer) {
+ c.log.Debug("Got Message: ", response)
+ consumerID := response.GetConsumerId()
+ if consumer, ok := c.consumerHandler(consumerID); ok {
+ err := consumer.MessageReceived(response, payload)
+ if err != nil {
+ c.log.
+ WithError(err).
+ WithField("consumerID", consumerID).
+ Error("handle message Id: ", response.MessageId)
+ }
+ } else {
+ c.log.WithField("consumerID", consumerID).Warn("Got unexpected message: ", response.MessageId)
+ }
+}
+
+func (c *connection) deletePendingRequest(requestID uint64) (*request, bool) {
+ c.pendingLock.Lock()
+ defer c.pendingLock.Unlock()
+ request, ok := c.pendingReqs[requestID]
+ if ok {
+ delete(c.pendingReqs, requestID)
+ }
+ return request, ok
+}
+
+func (c *connection) findPendingRequest(requestID uint64) (*request, bool) {
+ c.pendingLock.Lock()
+ defer c.pendingLock.Unlock()
+ request, ok := c.pendingReqs[requestID]
+ return request, ok
+}
+
+func (c *connection) failPendingRequests(err error) bool {
+ c.pendingLock.Lock()
+ defer c.pendingLock.Unlock()
+ for id, req := range c.pendingReqs {
+ req.callback(nil, err)
+ delete(c.pendingReqs, id)
+ }
+ return true
+}
+
+func (c *connection) lastDataReceived() time.Time {
+ c.lastDataReceivedLock.Lock()
+ defer c.lastDataReceivedLock.Unlock()
+ t := c.lastDataReceivedTime
+ return t
+}
+
+func (c *connection) setLastDataReceived(t time.Time) {
+ c.lastDataReceivedLock.Lock()
+ defer c.lastDataReceivedLock.Unlock()
+ c.lastDataReceivedTime = t
+}
+
+func (c *connection) sendPing() {
+ c.log.Debug("Sending PING")
+ c.writeCommand(baseCommand(pb.BaseCommand_PING, &pb.CommandPing{}))
+}
+
+func (c *connection) handlePong() {
+ c.log.Debug("Received PONG response")
+}
+
+func (c *connection) handlePing() {
+ c.log.Debug("Responding to PING request")
+ c.writeCommand(baseCommand(pb.BaseCommand_PONG, &pb.CommandPong{}))
+}
+
+func (c *connection) handleAuthChallenge(authChallenge *pb.CommandAuthChallenge) {
+ c.log.Debugf("Received auth challenge from broker: %s", authChallenge.GetChallenge().GetAuthMethodName())
+
+ // Get new credentials from the provider
+ authData, err := c.auth.GetData()
+ if err != nil {
+ c.log.WithError(err).Warn("Failed to load auth credentials")
+ c.Close()
+ return
+ }
+
+ cmdAuthResponse := &pb.CommandAuthResponse{
+ ProtocolVersion: proto.Int32(PulsarProtocolVersion),
+ ClientVersion: proto.String(ClientVersionString),
+ Response: &pb.AuthData{
+ AuthMethodName: proto.String(c.auth.Name()),
+ AuthData: authData,
+ },
+ }
+
+ c.writeCommand(baseCommand(pb.BaseCommand_AUTH_RESPONSE, cmdAuthResponse))
+}
+
+func (c *connection) handleSendError(sendError *pb.CommandSendError) {
+ c.log.Warnf("Received send error from server: [%v] : [%s]", sendError.GetError(), sendError.GetMessage())
+
+ producerID := sendError.GetProducerId()
+
+ switch sendError.GetError() {
+ case pb.ServerError_NotAllowedError:
+ _, ok := c.deletePendingProducers(producerID)
+ if !ok {
+ c.log.Warnf("Received unexpected error response for request %d of type %s",
+ producerID, sendError.GetError())
+ return
+ }
+
+ c.log.Warnf("server error: %s: %s", sendError.GetError(), sendError.GetMessage())
+ case pb.ServerError_TopicTerminatedError:
+ _, ok := c.deletePendingProducers(producerID)
+ if !ok {
+ c.log.Warnf("Received unexpected error response for producer %d of type %s",
+ producerID, sendError.GetError())
+ return
+ }
+ c.log.Warnf("server error: %s: %s", sendError.GetError(), sendError.GetMessage())
+ default:
+ // By default, for transient error, let the reconnection logic
+ // to take place and re-establish the produce again
+ c.Close()
+ }
+}
+
+func (c *connection) deletePendingProducers(producerID uint64) (ConnectionListener, bool) {
+ c.listenersLock.Lock()
+ producer, ok := c.listeners[producerID]
+ if ok {
+ delete(c.listeners, producerID)
+ }
+ c.listenersLock.Unlock()
+
+ return producer, ok
+}
+
+func (c *connection) handleCloseConsumer(closeConsumer *pb.CommandCloseConsumer) {
+ consumerID := closeConsumer.GetConsumerId()
+ c.log.Infof("Broker notification of Closed consumer: %d", consumerID)
+
+ if consumer, ok := c.consumerHandler(consumerID); ok {
+ consumer.ConnectionClosed()
+ c.DeleteConsumeHandler(consumerID)
+ } else {
+ c.log.WithField("consumerID", consumerID).Warnf("Consumer with ID not found while closing consumer")
+ }
+}
+
+func (c *connection) handleActiveConsumerChange(consumerChange *pb.CommandActiveConsumerChange) {
+ consumerID := consumerChange.GetConsumerId()
+ isActive := consumerChange.GetIsActive()
+ if consumer, ok := c.consumerHandler(consumerID); ok {
+ consumer.ActiveConsumerChanged(isActive)
+ } else {
+ c.log.WithField("consumerID", consumerID).Warnf("Consumer not found while active consumer change")
+ }
+}
+
+func (c *connection) handleCloseProducer(closeProducer *pb.CommandCloseProducer) {
+ c.log.Infof("Broker notification of Closed producer: %d", closeProducer.GetProducerId())
+ producerID := closeProducer.GetProducerId()
+
+ producer, ok := c.deletePendingProducers(producerID)
+ // did we find a producer?
+ if ok {
+ producer.ConnectionClosed()
+ } else {
+ c.log.WithField("producerID", producerID).Warn("Producer with ID not found while closing producer")
+ }
+}
+
+func (c *connection) RegisterListener(id uint64, listener ConnectionListener) error {
+ // do not add if connection is closed
+ if c.closed() {
+ c.log.Warnf("Connection closed unable register listener id=%+v", id)
+ return errUnableRegisterListener
+ }
+
+ c.listenersLock.Lock()
+ defer c.listenersLock.Unlock()
+
+ c.listeners[id] = listener
+ return nil
+}
+
+func (c *connection) UnregisterListener(id uint64) {
+ c.listenersLock.Lock()
+ defer c.listenersLock.Unlock()
+
+ delete(c.listeners, id)
+}
+
+func (c *connection) ResetLastActive() {
+ c.Lock()
+ defer c.Unlock()
+ c.lastActive = time.Now()
+}
+
+func (c *connection) isIdle() bool {
+ {
+ c.pendingLock.Lock()
+ defer c.pendingLock.Unlock()
+ if len(c.pendingReqs) != 0 {
+ return false
+ }
+ }
+
+ {
+ c.listenersLock.RLock()
+ defer c.listenersLock.RUnlock()
+ if len(c.listeners) != 0 {
+ return false
+ }
+ }
+
+ {
+ c.consumerHandlersLock.Lock()
+ defer c.consumerHandlersLock.Unlock()
+ if len(c.consumerHandlers) != 0 {
+ return false
+ }
+ }
+
+ if len(c.incomingRequestsCh) != 0 || len(c.writeRequestsCh) != 0 {
+ return false
+ }
+ return true
+}
+
+func (c *connection) CheckIdle(maxIdleTime time.Duration) bool {
+ // We don't need to lock here because this method should only be
+ // called in a single goroutine of the connectionPool
+ if !c.isIdle() {
+ c.lastActive = time.Now()
+ }
+ return time.Since(c.lastActive) > maxIdleTime
+}
+
+// Close closes the connection by
+// closing underlying socket connection and closeCh.
+// This also triggers callbacks to the ConnectionClosed listeners.
+func (c *connection) Close() {
+ c.closeOnce.Do(func() {
+ c.Lock()
+ cnx := c.cnx
+ c.Unlock()
+ c.changeState(connectionClosed)
+
+ if cnx != nil {
+ _ = cnx.Close()
+ }
+
+ close(c.closeCh)
+
+ listeners := make(map[uint64]ConnectionListener)
+ c.listenersLock.Lock()
+ for id, listener := range c.listeners {
+ listeners[id] = listener
+ delete(c.listeners, id)
+ }
+ c.listenersLock.Unlock()
+
+ consumerHandlers := make(map[uint64]ConsumerHandler)
+ c.consumerHandlersLock.Lock()
+ for id, handler := range c.consumerHandlers {
+ consumerHandlers[id] = handler
+ delete(c.consumerHandlers, id)
+ }
+ c.consumerHandlersLock.Unlock()
+
+ // notify producers connection closed
+ for _, listener := range listeners {
+ listener.ConnectionClosed()
+ }
+
+ // notify consumers connection closed
+ for _, handler := range consumerHandlers {
+ handler.ConnectionClosed()
+ }
+
+ c.metrics.ConnectionsClosed.Inc()
+ })
+}
+
+func (c *connection) changeState(state connectionState) {
+ // The lock is held here because we need setState() and cond.Broadcast() to be
+ // an atomic operation from the point of view of waitUntilReady().
+ c.Lock()
+ defer c.Unlock()
+
+ c.setState(state)
+ c.cond.Broadcast()
+}
+
+func (c *connection) getState() connectionState {
+ return connectionState(c.state.Load())
+}
+
+func (c *connection) setState(state connectionState) {
+ c.state.Store(int32(state))
+}
+
+func (c *connection) closed() bool {
+ return connectionClosed == c.getState()
+}
+
+func (c *connection) getTLSConfig() (*tls.Config, error) {
+ tlsConfig := &tls.Config{
+ InsecureSkipVerify: c.tlsOptions.AllowInsecureConnection,
+ }
+
+ if c.tlsOptions.TrustCertsFilePath != "" {
+ caCerts, err := os.ReadFile(c.tlsOptions.TrustCertsFilePath)
+ if err != nil {
+ return nil, err
+ }
+
+ tlsConfig.RootCAs = x509.NewCertPool()
+ ok := tlsConfig.RootCAs.AppendCertsFromPEM(caCerts)
+ if !ok {
+ return nil, errors.New("failed to parse root CAs certificates")
+ }
+ }
+
+ if c.tlsOptions.ValidateHostname {
+ if c.tlsOptions.ServerName != "" {
+ tlsConfig.ServerName = c.tlsOptions.ServerName
+ } else {
+ tlsConfig.ServerName = c.physicalAddr.Hostname()
+ }
+ c.log.Debugf("getTLSConfig(): setting tlsConfig.ServerName = %+v", tlsConfig.ServerName)
+ }
+
+ if c.tlsOptions.CertFile != "" && c.tlsOptions.KeyFile != "" {
+ cert, err := tls.LoadX509KeyPair(c.tlsOptions.CertFile, c.tlsOptions.KeyFile)
+ if err != nil {
+ return nil, errors.New(err.Error())
+ }
+ tlsConfig.Certificates = []tls.Certificate{cert}
+ }
+
+ cert, err := c.auth.GetTLSCertificate()
+ if err != nil {
+ return nil, err
+ }
+
+ if cert != nil {
+ tlsConfig.Certificates = []tls.Certificate{*cert}
+ }
+
+ return tlsConfig, nil
+}
+
+func (c *connection) AddConsumeHandler(id uint64, handler ConsumerHandler) error {
+ // do not add if connection is closed
+ if c.closed() {
+ c.log.Warnf("Closed connection unable add consumer with id=%+v", id)
+ return errUnableAddConsumeHandler
+ }
+
+ c.consumerHandlersLock.Lock()
+ defer c.consumerHandlersLock.Unlock()
+ c.consumerHandlers[id] = handler
+ return nil
+}
+
+func (c *connection) DeleteConsumeHandler(id uint64) {
+ c.consumerHandlersLock.Lock()
+ defer c.consumerHandlersLock.Unlock()
+ delete(c.consumerHandlers, id)
+}
+
+func (c *connection) consumerHandler(id uint64) (ConsumerHandler, bool) {
+ c.consumerHandlersLock.RLock()
+ defer c.consumerHandlersLock.RUnlock()
+ h, ok := c.consumerHandlers[id]
+ return h, ok
+}
+
+func (c *connection) ID() string {
+ return fmt.Sprintf("%s -> %s", c.cnx.LocalAddr(), c.cnx.RemoteAddr())
+}
+
+func (c *connection) GetMaxMessageSize() int32 {
+ return c.maxMessageSize
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection_pool.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection_pool.go
new file mode 100644
index 00000000..6ff79919
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection_pool.go
@@ -0,0 +1,166 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "fmt"
+ "net/url"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/auth"
+
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+// ConnectionPool is a interface of connection pool.
+type ConnectionPool interface {
+ // GetConnection get a connection from ConnectionPool.
+ GetConnection(logicalAddr *url.URL, physicalAddr *url.URL) (Connection, error)
+
+ // Close all the connections in the pool
+ Close()
+}
+
+type connectionPool struct {
+ sync.Mutex
+ connections map[string]*connection
+ connectionTimeout time.Duration
+ tlsOptions *TLSOptions
+ auth auth.Provider
+ maxConnectionsPerHost int32
+ roundRobinCnt int32
+ keepAliveInterval time.Duration
+ closeCh chan struct{}
+
+ metrics *Metrics
+ log log.Logger
+}
+
+// NewConnectionPool init connection pool.
+func NewConnectionPool(
+ tlsOptions *TLSOptions,
+ auth auth.Provider,
+ connectionTimeout time.Duration,
+ keepAliveInterval time.Duration,
+ maxConnectionsPerHost int,
+ logger log.Logger,
+ metrics *Metrics,
+ connectionMaxIdleTime time.Duration) ConnectionPool {
+ p := &connectionPool{
+ connections: make(map[string]*connection),
+ tlsOptions: tlsOptions,
+ auth: auth,
+ connectionTimeout: connectionTimeout,
+ maxConnectionsPerHost: int32(maxConnectionsPerHost),
+ keepAliveInterval: keepAliveInterval,
+ log: logger,
+ metrics: metrics,
+ closeCh: make(chan struct{}),
+ }
+ go p.checkAndCleanIdleConnections(connectionMaxIdleTime)
+ return p
+}
+
+func (p *connectionPool) GetConnection(logicalAddr *url.URL, physicalAddr *url.URL) (Connection, error) {
+ key := p.getMapKey(logicalAddr)
+
+ p.Lock()
+ conn, ok := p.connections[key]
+ if ok {
+ p.log.Debugf("Found connection in pool key=%s logical_addr=%+v physical_addr=%+v",
+ key, conn.logicalAddr, conn.physicalAddr)
+
+ // When the current connection is in a closed state or the broker actively notifies that the
+ // current connection is closed, we need to remove the connection object from the current
+ // connection pool and create a new connection.
+ if conn.closed() {
+ p.log.Debugf("Removed connection from pool key=%s logical_addr=%+v physical_addr=%+v",
+ key, conn.logicalAddr, conn.physicalAddr)
+ delete(p.connections, key)
+ conn.Close()
+ conn = nil // set to nil so we create a new one
+ }
+ }
+
+ if conn == nil {
+ conn = newConnection(connectionOptions{
+ logicalAddr: logicalAddr,
+ physicalAddr: physicalAddr,
+ tls: p.tlsOptions,
+ connectionTimeout: p.connectionTimeout,
+ auth: p.auth,
+ keepAliveInterval: p.keepAliveInterval,
+ logger: p.log,
+ metrics: p.metrics,
+ })
+ p.connections[key] = conn
+ p.Unlock()
+ conn.start()
+ } else {
+ conn.ResetLastActive()
+ // we already have a connection
+ p.Unlock()
+ }
+
+ err := conn.waitUntilReady()
+ return conn, err
+}
+
+func (p *connectionPool) Close() {
+ p.Lock()
+ close(p.closeCh)
+ for k, c := range p.connections {
+ delete(p.connections, k)
+ c.Close()
+ }
+ p.Unlock()
+}
+
+func (p *connectionPool) getMapKey(addr *url.URL) string {
+ cnt := atomic.AddInt32(&p.roundRobinCnt, 1)
+ if cnt < 0 {
+ cnt = -cnt
+ }
+ idx := cnt % p.maxConnectionsPerHost
+ return fmt.Sprint(addr.Host, '-', idx)
+}
+
+func (p *connectionPool) checkAndCleanIdleConnections(maxIdleTime time.Duration) {
+ if maxIdleTime < 0 {
+ return
+ }
+ for {
+ select {
+ case <-p.closeCh:
+ return
+ case <-time.After(maxIdleTime):
+ p.Lock()
+ for k, c := range p.connections {
+ if c.CheckIdle(maxIdleTime) {
+ p.log.Debugf("Closed connection from pool due to inactivity. logical_addr=%+v physical_addr=%+v",
+ c.logicalAddr, c.physicalAddr)
+ delete(p.connections, k)
+ c.Close()
+ }
+ }
+ p.Unlock()
+ }
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection_reader.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection_reader.go
new file mode 100644
index 00000000..c451562c
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/connection_reader.go
@@ -0,0 +1,148 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "google.golang.org/protobuf/proto"
+)
+
+type connectionReader struct {
+ cnx *connection
+ buffer Buffer
+ reader *bufio.Reader
+}
+
+func newConnectionReader(cnx *connection) *connectionReader {
+ return &connectionReader{
+ cnx: cnx,
+ reader: bufio.NewReader(cnx.cnx),
+ buffer: NewBuffer(4096),
+ }
+}
+
+func (r *connectionReader) readFromConnection() {
+ for {
+ cmd, headersAndPayload, err := r.readSingleCommand()
+ if err != nil {
+ if !r.cnx.closed() {
+ r.cnx.log.WithError(err).Infof("Error reading from connection")
+ r.cnx.Close()
+ }
+ break
+ }
+
+ // Process
+ var payloadLen uint32
+ if headersAndPayload != nil {
+ payloadLen = headersAndPayload.ReadableBytes()
+ }
+ r.cnx.log.Debug("Got command! ", cmd, " with payload size: ", payloadLen, " maxMsgSize: ", r.cnx.maxMessageSize)
+ r.cnx.receivedCommand(cmd, headersAndPayload)
+ }
+}
+
+func (r *connectionReader) readSingleCommand() (cmd *pb.BaseCommand, headersAndPayload Buffer, err error) {
+ // First, we need to read the frame size
+ if r.buffer.ReadableBytes() < 4 {
+ if r.buffer.ReadableBytes() == 0 {
+ // If the buffer is empty, just go back to write at the beginning
+ r.buffer.Clear()
+ }
+ if err := r.readAtLeast(4); err != nil {
+ return nil, nil, fmt.Errorf("unable to read frame size: %+v", err)
+ }
+ }
+
+ // We have enough to read frame size
+ frameSize := r.buffer.ReadUint32()
+ maxFrameSize := r.cnx.maxMessageSize + MessageFramePadding
+ if r.cnx.maxMessageSize != 0 && int32(frameSize) > maxFrameSize {
+ frameSizeError := fmt.Errorf("received too big frame size=%d maxFrameSize=%d", frameSize, maxFrameSize)
+ r.cnx.log.Error(frameSizeError)
+ r.cnx.Close()
+ return nil, nil, frameSizeError
+ }
+
+ // Next, we read the rest of the frame
+ if r.buffer.ReadableBytes() < frameSize {
+ remainingBytes := frameSize - r.buffer.ReadableBytes()
+ if err := r.readAtLeast(remainingBytes); err != nil {
+ return nil, nil,
+ fmt.Errorf("unable to read frame: %+v", err)
+ }
+ }
+
+ // We have now the complete frame
+ cmdSize := r.buffer.ReadUint32()
+ cmd, err = r.deserializeCmd(r.buffer.Read(cmdSize))
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Also read the eventual payload
+ headersAndPayloadSize := frameSize - (cmdSize + 4)
+ if cmdSize+4 < frameSize {
+ headersAndPayload = NewBuffer(int(headersAndPayloadSize))
+ headersAndPayload.Write(r.buffer.Read(headersAndPayloadSize))
+ }
+ return cmd, headersAndPayload, nil
+}
+
+func (r *connectionReader) readAtLeast(size uint32) error {
+ if r.buffer.WritableBytes() < size {
+ // There's not enough room in the current buffer to read the requested amount of data
+ totalFrameSize := r.buffer.ReadableBytes() + size
+ if r.buffer.ReadableBytes()+size > r.buffer.Capacity() {
+ // Resize to a bigger buffer to avoid continuous resizing
+ r.buffer.Resize(totalFrameSize * 2)
+ } else {
+ // Compact the buffer by moving the partial data to the beginning.
+ // This will have enough room for reading the remainder of the data
+ r.buffer.MoveToFront()
+ }
+ }
+
+ n, err := io.ReadAtLeast(r.cnx.cnx, r.buffer.WritableSlice(), int(size))
+ if err != nil {
+ // has the connection been closed?
+ if r.cnx.closed() {
+ return errConnectionClosed
+ }
+ r.cnx.Close()
+ return err
+ }
+
+ r.buffer.WrittenBytes(uint32(n))
+ return nil
+}
+
+func (r *connectionReader) deserializeCmd(data []byte) (*pb.BaseCommand, error) {
+ cmd := &pb.BaseCommand{}
+ err := proto.Unmarshal(data, cmd)
+ if err != nil {
+ r.cnx.log.WithError(err).Warn("Failed to parse protobuf command")
+ r.cnx.Close()
+ return nil, err
+ }
+ return cmd, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/consumer_decryptor.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/consumer_decryptor.go
new file mode 100644
index 00000000..bbc1f9b1
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/consumer_decryptor.go
@@ -0,0 +1,60 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import (
+ "fmt"
+
+ "github.com/apache/pulsar-client-go/pulsar/crypto"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+type consumerDecryptor struct {
+ keyReader crypto.KeyReader
+ messageCrypto crypto.MessageCrypto
+ logger log.Logger
+}
+
+func NewConsumerDecryptor(keyReader crypto.KeyReader,
+ messageCrypto crypto.MessageCrypto,
+ logger log.Logger) Decryptor {
+ return &consumerDecryptor{
+ keyReader: keyReader,
+ messageCrypto: messageCrypto,
+ logger: logger,
+ }
+}
+
+func (d *consumerDecryptor) Decrypt(payload []byte,
+ msgID *pb.MessageIdData,
+ msgMetadata *pb.MessageMetadata) ([]byte, error) {
+ // encryption keys are not present in message metadta, no need decrypt the payload
+ if len(msgMetadata.GetEncryptionKeys()) == 0 {
+ return payload, nil
+ }
+
+ // KeyReader interface is not implemented
+ if d.keyReader == nil {
+ return payload, fmt.Errorf("KeyReader interface is not implemented")
+ }
+
+ return d.messageCrypto.Decrypt(crypto.NewMessageMetadataSupplier(msgMetadata),
+ payload,
+ d.keyReader)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/decryptor.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/decryptor.go
new file mode 100644
index 00000000..da67d5cd
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/decryptor.go
@@ -0,0 +1,27 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import (
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+// Decryptor support decrypting of message
+type Decryptor interface {
+ Decrypt(payload []byte, msgID *pb.MessageIdData, msgMetadata *pb.MessageMetadata) ([]byte, error)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/encryptor.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/encryptor.go
new file mode 100644
index 00000000..7fdbf06a
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/encryptor.go
@@ -0,0 +1,27 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import (
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+// Encryptor support encryption
+type Encryptor interface {
+ Encrypt([]byte, *pb.MessageMetadata) ([]byte, error)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/noop_decryptor.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/noop_decryptor.go
new file mode 100644
index 00000000..c049c472
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/noop_decryptor.go
@@ -0,0 +1,40 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import (
+ "fmt"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+type noopDecryptor struct{}
+
+func NewNoopDecryptor() Decryptor {
+ return &noopDecryptor{}
+}
+
+// Decrypt noop decryptor
+func (d *noopDecryptor) Decrypt(payload []byte,
+ msgID *pb.MessageIdData,
+ msgMetadata *pb.MessageMetadata) ([]byte, error) {
+ if len(msgMetadata.GetEncryptionKeys()) > 0 {
+ return payload, fmt.Errorf("incoming message payload is encrypted, consumer is not configured to decrypt")
+ }
+ return payload, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/noop_encryptor.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/noop_encryptor.go
new file mode 100644
index 00000000..4512e7bd
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/noop_encryptor.go
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import (
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+type noopEncryptor struct{}
+
+func NewNoopEncryptor() Encryptor {
+ return &noopEncryptor{}
+}
+
+// Encrypt Noop ecryptor
+func (e *noopEncryptor) Encrypt(data []byte, msgMetadata *pb.MessageMetadata) ([]byte, error) {
+ return data, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/producer_encryptor.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/producer_encryptor.go
new file mode 100644
index 00000000..a5b972da
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/crypto/producer_encryptor.go
@@ -0,0 +1,73 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package crypto
+
+import (
+ "fmt"
+
+ "github.com/apache/pulsar-client-go/pulsar/crypto"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+type producerEncryptor struct {
+ keys []string
+ keyReader crypto.KeyReader
+ messageCrypto crypto.MessageCrypto
+ logger log.Logger
+ producerCryptoFailureAction int
+}
+
+func NewProducerEncryptor(keys []string,
+ keyReader crypto.KeyReader,
+ messageCrypto crypto.MessageCrypto,
+ producerCryptoFailureAction int,
+ logger log.Logger) Encryptor {
+ return &producerEncryptor{
+ keys: keys,
+ keyReader: keyReader,
+ messageCrypto: messageCrypto,
+ logger: logger,
+ producerCryptoFailureAction: producerCryptoFailureAction,
+ }
+}
+
+// Encrypt producer encryptor
+func (e *producerEncryptor) Encrypt(payload []byte, msgMetadata *pb.MessageMetadata) ([]byte, error) {
+ // encrypt payload
+ encryptedPayload, err := e.messageCrypto.Encrypt(e.keys,
+ e.keyReader,
+ crypto.NewMessageMetadataSupplier(msgMetadata),
+ payload)
+
+ // error encryping the payload
+ if err != nil {
+ // error occurred in encrypting the payload
+ // crypto ProducerCryptoFailureAction is set to send
+ // send unencrypted message
+ if e.producerCryptoFailureAction == crypto.ProducerCryptoFailureActionSend {
+ e.logger.
+ WithError(err).
+ Warnf("Encryption failed for payload sending unencrypted message ProducerCryptoFailureAction is set to send")
+ return payload, nil
+ }
+
+ return nil, fmt.Errorf("ProducerCryptoFailureAction is set to Fail and error occurred in encrypting payload :%v", err)
+ }
+ return encryptedPayload, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/hash.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/hash.go
new file mode 100644
index 00000000..0ac85907
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/hash.go
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import "github.com/spaolacci/murmur3"
+
+// JavaStringHash and Java String.hashCode() equivalent
+func JavaStringHash(s string) uint32 {
+ var h uint32
+ for i, size := 0, len(s); i < size; i++ {
+ h = 31*h + uint32(s[i])
+ }
+
+ return h
+}
+
+// Murmur3_32Hash use Murmur3 hashing function
+func Murmur3_32Hash(s string) uint32 {
+ h := murmur3.New32()
+ _, err := h.Write([]byte(s))
+ if err != nil {
+ return 0
+ }
+ // Maintain compatibility with values used in Java client
+ return h.Sum32() & 0x7fffffff
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/helper.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/helper.go
new file mode 100644
index 00000000..3bca1ee0
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/helper.go
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import "time"
+
+// These method should only be used by tests
+
+func StartCleanConnectionsTask(p *ConnectionPool, connectionMaxIdleTime time.Duration) {
+ go (*p).(*connectionPool).checkAndCleanIdleConnections(connectionMaxIdleTime)
+}
+
+func GetConnectionsCount(p *ConnectionPool) int {
+ pool := (*p).(*connectionPool)
+ pool.Lock()
+ defer pool.Unlock()
+ return len(pool.connections)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/http_client.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/http_client.go
new file mode 100644
index 00000000..dccc1431
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/http_client.go
@@ -0,0 +1,360 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "bytes"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/json"
+ "io"
+ "net/http"
+ "net/url"
+ "os"
+ "path"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/auth"
+
+ "github.com/apache/pulsar-client-go/pulsar/log"
+
+ "github.com/pkg/errors"
+)
+
+// httpClient is a base client that is used to make http httpRequest to the ServiceURL
+type httpClient struct {
+ ServiceNameResolver ServiceNameResolver
+ HTTPClient *http.Client
+ requestTimeout time.Duration
+ log log.Logger
+ metrics *Metrics
+}
+
+func (c *httpClient) Close() {
+ if c.HTTPClient != nil {
+ c.HTTPClient.CloseIdleConnections()
+ }
+}
+
+type HTTPClient interface {
+ Get(endpoint string, obj interface{}, params map[string]string) error
+ Closable
+}
+
+func NewHTTPClient(serviceURL *url.URL, serviceNameResolver ServiceNameResolver, tlsConfig *TLSOptions,
+ requestTimeout time.Duration, logger log.Logger, metrics *Metrics,
+ authProvider auth.Provider) (HTTPClient, error) {
+ h := &httpClient{
+ ServiceNameResolver: serviceNameResolver,
+ requestTimeout: requestTimeout,
+ log: logger.SubLogger(log.Fields{"serviceURL": serviceURL}),
+ metrics: metrics,
+ }
+ c := &http.Client{Timeout: requestTimeout}
+ transport, err := getDefaultTransport(tlsConfig)
+ if err != nil {
+ return nil, err
+ }
+ c.Transport = transport
+ if authProvider.Name() != "" {
+ err = authProvider.WithTransport(c.Transport)
+ if err != nil {
+ return nil, err
+ }
+ c.Transport = authProvider
+ }
+ h.HTTPClient = c
+ return h, nil
+}
+
+func (c *httpClient) newRequest(method, path string) (*httpRequest, error) {
+ base, err := c.ServiceNameResolver.ResolveHost()
+ if err != nil {
+ return nil, err
+ }
+
+ u, err := url.Parse(path)
+ if err != nil {
+ return nil, err
+ }
+
+ req := &httpRequest{
+ method: method,
+ url: &url.URL{
+ Scheme: base.Scheme,
+ User: base.User,
+ Host: base.Host,
+ Path: endpoint(base.Path, u.Path),
+ },
+ params: make(url.Values),
+ }
+ return req, nil
+}
+
+func (c *httpClient) doRequest(r *httpRequest) (*http.Response, error) {
+ req, err := r.toHTTP()
+ if err != nil {
+ return nil, err
+ }
+
+ if r.contentType != "" {
+ req.Header.Set("Content-Type", r.contentType)
+ } else if req.Body != nil {
+ req.Header.Set("Content-Type", "application/json")
+ }
+
+ req.Header.Set("Accept", "application/json")
+ req.Header.Set("User-Agent", c.useragent())
+ hc := c.HTTPClient
+ if hc == nil {
+ hc = http.DefaultClient
+ }
+
+ return hc.Do(req)
+}
+
+// MakeRequest can make a simple httpRequest and handle the response by yourself
+func (c *httpClient) MakeRequest(method, endpoint string) (*http.Response, error) {
+ req, err := c.newRequest(method, endpoint)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := checkSuccessful(c.doRequest(req))
+ if err != nil {
+ return nil, err
+ }
+
+ return resp, nil
+}
+
+func (c *httpClient) Get(endpoint string, obj interface{}, params map[string]string) error {
+ _, err := c.GetWithQueryParams(endpoint, obj, params, true)
+ if _, ok := err.(*url.Error); ok {
+ // We can retry this kind of requests over a connection error because they're
+ // not specific to a particular broker.
+ backoff := DefaultBackoff{100 * time.Millisecond}
+ startTime := time.Now()
+ var retryTime time.Duration
+
+ for time.Since(startTime) < c.requestTimeout {
+ retryTime = backoff.Next()
+ c.log.Debugf("Retrying httpRequest in {%v} with timeout in {%v}", retryTime, c.requestTimeout)
+ time.Sleep(retryTime)
+ _, err = c.GetWithQueryParams(endpoint, obj, params, true)
+ if _, ok := err.(*url.Error); ok {
+ continue
+ } else {
+ // We either succeeded or encountered a non connection error
+ break
+ }
+ }
+ }
+ return err
+}
+
+func (c *httpClient) GetWithQueryParams(endpoint string, obj interface{}, params map[string]string,
+ decode bool) ([]byte, error) {
+ return c.GetWithOptions(endpoint, obj, params, decode, nil)
+}
+
+func (c *httpClient) GetWithOptions(endpoint string, obj interface{}, params map[string]string,
+ decode bool, file io.Writer) ([]byte, error) {
+
+ req, err := c.newRequest(http.MethodGet, endpoint)
+ if err != nil {
+ return nil, err
+ }
+
+ if params != nil {
+ query := req.url.Query()
+ for k, v := range params {
+ query.Add(k, v)
+ }
+ req.params = query
+ }
+
+ resp, err := checkSuccessful(c.doRequest(req))
+ if err != nil {
+ return nil, err
+ }
+ defer safeRespClose(resp)
+
+ if obj != nil {
+ if err := decodeJSONBody(resp, &obj); err != nil {
+ if err == io.EOF {
+ return nil, nil
+ }
+ return nil, err
+ }
+ } else if !decode {
+ if file != nil {
+ _, err := io.Copy(file, resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ return body, err
+ }
+ }
+
+ return nil, err
+}
+
+func (c *httpClient) useragent() string {
+ return "Pulsar-httpClient-Go-v2"
+}
+
+type httpRequest struct {
+ method string
+ contentType string
+ url *url.URL
+ params url.Values
+
+ obj interface{}
+ body io.Reader
+}
+
+func (r *httpRequest) toHTTP() (*http.Request, error) {
+ r.url.RawQuery = r.params.Encode()
+
+ // add a httpRequest body if there is one
+ if r.body == nil && r.obj != nil {
+ body, err := encodeJSONBody(r.obj)
+ if err != nil {
+ return nil, err
+ }
+ r.body = body
+ }
+
+ req, err := http.NewRequest(r.method, r.url.RequestURI(), r.body)
+ if err != nil {
+ return nil, err
+ }
+
+ req.URL.Host = r.url.Host
+ req.URL.Scheme = r.url.Scheme
+ req.Host = r.url.Host
+ return req, nil
+}
+
+// respIsOk is used to validate a successful http status code
+func respIsOk(resp *http.Response) bool {
+ return resp.StatusCode >= http.StatusOK && resp.StatusCode <= http.StatusNoContent
+}
+
+// checkSuccessful checks for a valid response and parses an error
+func checkSuccessful(resp *http.Response, err error) (*http.Response, error) {
+ if err != nil {
+ safeRespClose(resp)
+ return nil, err
+ }
+
+ if !respIsOk(resp) {
+ defer safeRespClose(resp)
+ return nil, responseError(resp)
+ }
+
+ return resp, nil
+}
+
+func endpoint(parts ...string) string {
+ return path.Join(parts...)
+}
+
+// encodeJSONBody is used to JSON encode a body
+func encodeJSONBody(obj interface{}) (io.Reader, error) {
+ buf := bytes.NewBuffer(nil)
+ enc := json.NewEncoder(buf)
+ if err := enc.Encode(obj); err != nil {
+ return nil, err
+ }
+ return buf, nil
+}
+
+// decodeJSONBody is used to JSON decode a body
+func decodeJSONBody(resp *http.Response, out interface{}) error {
+ if resp.ContentLength == 0 {
+ return nil
+ }
+ dec := json.NewDecoder(resp.Body)
+ return dec.Decode(out)
+}
+
+// safeRespClose is used to close a response body
+func safeRespClose(resp *http.Response) {
+ if resp != nil {
+ // ignore error since it is closing a response body
+ _ = resp.Body.Close()
+ }
+}
+
+// responseError is used to parse a response into a client error
+func responseError(resp *http.Response) error {
+ var e error
+ body, err := io.ReadAll(resp.Body)
+ reason := ""
+ code := resp.StatusCode
+ if err != nil {
+ reason = err.Error()
+ return errors.Errorf("Code: %d, Reason: %s", code, reason)
+ }
+
+ err = json.Unmarshal(body, &e)
+ if err != nil {
+ reason = string(body)
+ }
+
+ if reason == "" {
+ reason = "Unknown error"
+ }
+
+ return errors.Errorf("Code: %d, Reason: %s", code, reason)
+}
+
+func getDefaultTransport(tlsConfig *TLSOptions) (http.RoundTripper, error) {
+ transport := http.DefaultTransport.(*http.Transport)
+ if tlsConfig != nil {
+ cfg := &tls.Config{
+ InsecureSkipVerify: tlsConfig.AllowInsecureConnection,
+ }
+ if len(tlsConfig.TrustCertsFilePath) > 0 {
+ rootCA, err := os.ReadFile(tlsConfig.TrustCertsFilePath)
+ if err != nil {
+ return nil, err
+ }
+ cfg.RootCAs = x509.NewCertPool()
+ cfg.RootCAs.AppendCertsFromPEM(rootCA)
+ }
+
+ if tlsConfig.CertFile != "" && tlsConfig.KeyFile != "" {
+ cert, err := tls.LoadX509KeyPair(tlsConfig.CertFile, tlsConfig.KeyFile)
+ if err != nil {
+ return nil, errors.New(err.Error())
+ }
+ cfg.Certificates = []tls.Certificate{cert}
+ }
+ transport.TLSClientConfig = cfg
+ }
+ transport.MaxIdleConnsPerHost = 10
+ return transport, nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/key_based_batch_builder.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/key_based_batch_builder.go
new file mode 100644
index 00000000..334e6746
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/key_based_batch_builder.go
@@ -0,0 +1,251 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "encoding/base64"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal/compression"
+ "github.com/apache/pulsar-client-go/pulsar/internal/crypto"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+/**
+ * Key based batch message container
+ *
+ * incoming single messages:
+ * (k1, v1), (k2, v1), (k3, v1), (k1, v2), (k2, v2), (k3, v2), (k1, v3), (k2, v3), (k3, v3)
+ *
+ * batched into multiple batch messages:
+ * [(k1, v1), (k1, v2), (k1, v3)], [(k2, v1), (k2, v2), (k2, v3)], [(k3, v1), (k3, v2), (k3, v3)]
+ */
+
+// keyBasedBatches is a simple concurrent-safe map for the batchContainer type
+type keyBasedBatches struct {
+ containers map[string]*batchContainer
+ l *sync.RWMutex
+}
+
+// keyBasedBatchContainer wraps the objects needed to key based batch.
+// keyBasedBatchContainer implement BatchBuilder as a multiple batches
+// container.
+type keyBasedBatchContainer struct {
+ batches keyBasedBatches
+ batchContainer
+ compressionType pb.CompressionType
+ level compression.Level
+}
+
+// newKeyBasedBatches init a keyBasedBatches
+func newKeyBasedBatches() keyBasedBatches {
+ return keyBasedBatches{
+ containers: map[string]*batchContainer{},
+ l: &sync.RWMutex{},
+ }
+}
+
+func (h *keyBasedBatches) Add(key string, val *batchContainer) {
+ h.l.Lock()
+ defer h.l.Unlock()
+ h.containers[key] = val
+}
+
+func (h *keyBasedBatches) Del(key string) {
+ h.l.Lock()
+ defer h.l.Unlock()
+ delete(h.containers, key)
+}
+
+func (h *keyBasedBatches) Val(key string) *batchContainer {
+ h.l.RLock()
+ defer h.l.RUnlock()
+ return h.containers[key]
+}
+
+// NewKeyBasedBatchBuilder init batch builder and return BatchBuilder
+// pointer. Build a new key based batch message container.
+func NewKeyBasedBatchBuilder(
+ maxMessages uint, maxBatchSize uint, maxMessageSize uint32, producerName string, producerID uint64,
+ compressionType pb.CompressionType, level compression.Level,
+ bufferPool BuffersPool, logger log.Logger, encryptor crypto.Encryptor,
+) (BatchBuilder, error) {
+
+ bb := &keyBasedBatchContainer{
+ batches: newKeyBasedBatches(),
+ batchContainer: newBatchContainer(
+ maxMessages, maxBatchSize, maxMessageSize, producerName, producerID,
+ compressionType, level, bufferPool, logger, encryptor,
+ ),
+ compressionType: compressionType,
+ level: level,
+ }
+
+ if compressionType != pb.CompressionType_NONE {
+ bb.msgMetadata.Compression = &compressionType
+ }
+
+ return bb, nil
+}
+
+// IsFull checks if the size in the current batch meets or exceeds the maximum size allowed by the batch
+func (bc *keyBasedBatchContainer) IsFull() bool {
+ return bc.numMessages >= bc.maxMessages || bc.buffer.ReadableBytes() >= uint32(bc.maxBatchSize)
+}
+
+func (bc *keyBasedBatchContainer) IsMultiBatches() bool {
+ return true
+}
+
+// hasSpace should return true if and only if the batch container can accommodate another message of length payload.
+func (bc *keyBasedBatchContainer) hasSpace(payload []byte) bool {
+ if bc.numMessages == 0 {
+ // allow to add at least one message
+ // and a single max message size is checked in the producer partition, therefore no need to validate batch size
+ return true
+ }
+ msgSize := uint32(len(payload))
+ return bc.numMessages+1 <= bc.maxMessages && bc.buffer.ReadableBytes()+msgSize <= uint32(bc.maxBatchSize)
+}
+
+// Add will add single message to key-based batch with message key.
+func (bc *keyBasedBatchContainer) Add(
+ metadata *pb.SingleMessageMetadata, sequenceIDGenerator *uint64,
+ payload []byte,
+ callback interface{}, replicateTo []string, deliverAt time.Time,
+ schemaVersion []byte, multiSchemaEnabled bool,
+) bool {
+ if replicateTo != nil && bc.numMessages != 0 {
+ // If the current batch is not empty and we're trying to set the replication clusters,
+ // then we need to force the current batch to flush and send the message individually
+ return false
+ } else if bc.msgMetadata.ReplicateTo != nil {
+ // There's already a message with cluster replication list. need to flush before next
+ // message can be sent
+ return false
+ } else if !bc.hasSpace(payload) {
+ // The current batch is full. Producer has to call Flush() to
+ return false
+ }
+
+ var msgKey = getMessageKey(metadata)
+ batchPart := bc.batches.Val(msgKey)
+ if batchPart == nil {
+ // create batchContainer for new key
+ t := newBatchContainer(
+ bc.maxMessages, bc.maxBatchSize, bc.maxMessageSize, bc.producerName, bc.producerID,
+ bc.compressionType, bc.level, bc.buffersPool, bc.log, bc.encryptor,
+ )
+ batchPart = &t
+ bc.batches.Add(msgKey, &t)
+ }
+
+ // add message to batch container
+ add := batchPart.Add(
+ metadata, sequenceIDGenerator, payload, callback, replicateTo,
+ deliverAt,
+ schemaVersion, multiSchemaEnabled,
+ )
+ if !add {
+ return false
+ }
+ addSingleMessageToBatch(bc.buffer, metadata, payload)
+
+ bc.numMessages++
+ bc.callbacks = append(bc.callbacks, callback)
+ return true
+}
+
+func (bc *keyBasedBatchContainer) reset() {
+ bc.batches.l.RLock()
+ defer bc.batches.l.RUnlock()
+ for _, container := range bc.batches.containers {
+ container.reset()
+ }
+ bc.numMessages = 0
+ bc.buffer.Clear()
+ bc.callbacks = []interface{}{}
+ bc.msgMetadata.ReplicateTo = nil
+ bc.msgMetadata.DeliverAtTime = nil
+ bc.batches.containers = map[string]*batchContainer{}
+}
+
+// Flush all the messages buffered in multiple batches and wait until all
+// messages have been successfully persisted.
+func (bc *keyBasedBatchContainer) FlushBatches() (
+ batchesData []Buffer, sequenceIDs []uint64, callbacks [][]interface{}, errors []error,
+) {
+ if bc.numMessages == 0 {
+ // No-Op for empty batch
+ return nil, nil, nil, nil
+ }
+
+ bc.log.Debug("keyBasedBatchContainer flush: messages: ", bc.numMessages)
+ var batchesLen = len(bc.batches.containers)
+ var idx = 0
+ sortedKeys := make([]string, 0, batchesLen)
+
+ batchesData = make([]Buffer, batchesLen)
+ sequenceIDs = make([]uint64, batchesLen)
+ callbacks = make([][]interface{}, batchesLen)
+ errors = make([]error, batchesLen)
+
+ bc.batches.l.RLock()
+ defer bc.batches.l.RUnlock()
+ for k := range bc.batches.containers {
+ sortedKeys = append(sortedKeys, k)
+ }
+ sort.Strings(sortedKeys)
+ for _, k := range sortedKeys {
+ container := bc.batches.containers[k]
+ b, s, c, err := container.Flush()
+ if b != nil {
+ batchesData[idx] = b
+ sequenceIDs[idx] = s
+ callbacks[idx] = c
+ errors[idx] = err
+ }
+ idx++
+ }
+
+ bc.reset()
+ return batchesData, sequenceIDs, callbacks, errors
+}
+
+func (bc *keyBasedBatchContainer) Flush() (
+ batchData Buffer, sequenceID uint64, callbacks []interface{}, err error,
+) {
+ panic("multi batches container not support Flush(), please use FlushBatches() instead")
+}
+
+func (bc *keyBasedBatchContainer) Close() error {
+ return bc.compressionProvider.Close()
+}
+
+// getMessageKey extracts message key from message metadata.
+// If the OrderingKey exists, the base64-encoded string is returned,
+// otherwise the PartitionKey is returned.
+func getMessageKey(metadata *pb.SingleMessageMetadata) string {
+ if k := metadata.GetOrderingKey(); k != nil {
+ return base64.StdEncoding.EncodeToString(k)
+ }
+ return metadata.GetPartitionKey()
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/lookup_service.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/lookup_service.go
new file mode 100644
index 00000000..e30bec1d
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/lookup_service.go
@@ -0,0 +1,399 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "errors"
+ "fmt"
+ "net/url"
+
+ "google.golang.org/protobuf/proto"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+// LookupResult encapsulates a struct for lookup a request, containing two parts: LogicalAddr, PhysicalAddr.
+type LookupResult struct {
+ LogicalAddr *url.URL
+ PhysicalAddr *url.URL
+}
+
+// GetTopicsOfNamespaceMode for CommandGetTopicsOfNamespace_Mode
+type GetTopicsOfNamespaceMode string
+
+const (
+ Persistent GetTopicsOfNamespaceMode = "PERSISTENT"
+ NonPersistent = "NON_PERSISTENT"
+ All = "ALL"
+)
+
+// PartitionedTopicMetadata encapsulates a struct for metadata of a partitioned topic
+type PartitionedTopicMetadata struct {
+ Partitions int `json:"partitions"` // Number of partitions for the topic
+}
+
+// LookupService is a interface of lookup service.
+type LookupService interface {
+ // Lookup perform a lookup for the given topic, confirm the location of the broker
+ // where the topic is located, and return the LookupResult.
+ Lookup(topic string) (*LookupResult, error)
+
+ // GetPartitionedTopicMetadata perform a CommandPartitionedTopicMetadata request for
+ // the given topic, returns the CommandPartitionedTopicMetadataResponse as the result.
+ GetPartitionedTopicMetadata(topic string) (*PartitionedTopicMetadata, error)
+
+ // GetTopicsOfNamespace returns all the topics name for a given namespace.
+ GetTopicsOfNamespace(namespace string, mode GetTopicsOfNamespaceMode) ([]string, error)
+
+ // GetSchema returns schema for a given version.
+ GetSchema(topic string, schemaVersion []byte) (schema *pb.Schema, err error)
+
+ // Closable Allow Lookup Service's internal client to be able to closed
+ Closable
+}
+
+type lookupService struct {
+ rpcClient RPCClient
+ serviceNameResolver ServiceNameResolver
+ tlsEnabled bool
+ listenerName string
+ log log.Logger
+ metrics *Metrics
+}
+
+// NewLookupService init a lookup service struct and return an object of LookupService.
+func NewLookupService(rpcClient RPCClient, serviceURL *url.URL, serviceNameResolver ServiceNameResolver,
+ tlsEnabled bool, listenerName string, logger log.Logger, metrics *Metrics) LookupService {
+ return &lookupService{
+ rpcClient: rpcClient,
+ serviceNameResolver: serviceNameResolver,
+ tlsEnabled: tlsEnabled,
+ log: logger.SubLogger(log.Fields{"serviceURL": serviceURL}),
+ metrics: metrics,
+ listenerName: listenerName,
+ }
+}
+
+func (ls *lookupService) GetSchema(topic string, schemaVersion []byte) (schema *pb.Schema, err error) {
+ id := ls.rpcClient.NewRequestID()
+ req := &pb.CommandGetSchema{
+ RequestId: proto.Uint64(id),
+ Topic: proto.String(topic),
+ SchemaVersion: schemaVersion,
+ }
+ res, err := ls.rpcClient.RequestToAnyBroker(id, pb.BaseCommand_GET_SCHEMA, req)
+ if err != nil {
+ return nil, err
+ }
+ if res.Response.Error != nil {
+ return nil, errors.New(res.Response.GetError().String())
+ }
+ return res.Response.GetSchemaResponse.Schema, nil
+}
+
+func (ls *lookupService) getBrokerAddress(lr *pb.CommandLookupTopicResponse) (logicalAddress *url.URL,
+ physicalAddress *url.URL, err error) {
+ if ls.tlsEnabled {
+ logicalAddress, err = url.ParseRequestURI(lr.GetBrokerServiceUrlTls())
+ } else {
+ logicalAddress, err = url.ParseRequestURI(lr.GetBrokerServiceUrl())
+ }
+
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var physicalAddr *url.URL
+ if lr.GetProxyThroughServiceUrl() {
+ physicalAddr, err = ls.serviceNameResolver.ResolveHost()
+ if err != nil {
+ return nil, nil, err
+ }
+ } else {
+ physicalAddr = logicalAddress
+ }
+
+ return logicalAddress, physicalAddr, nil
+}
+
+// Follow brokers redirect up to certain number of times
+const lookupResultMaxRedirect = 20
+
+func (ls *lookupService) Lookup(topic string) (*LookupResult, error) {
+ ls.metrics.LookupRequestsCount.Inc()
+ id := ls.rpcClient.NewRequestID()
+ res, err := ls.rpcClient.RequestToAnyBroker(id, pb.BaseCommand_LOOKUP, &pb.CommandLookupTopic{
+ RequestId: &id,
+ Topic: &topic,
+ Authoritative: proto.Bool(false),
+ AdvertisedListenerName: proto.String(ls.listenerName),
+ })
+ if err != nil {
+ return nil, err
+ }
+ ls.log.Debugf("Got topic{%s} lookup response: %+v", topic, res)
+
+ for i := 0; i < lookupResultMaxRedirect; i++ {
+ lr := res.Response.LookupTopicResponse
+ switch *lr.Response {
+
+ case pb.CommandLookupTopicResponse_Redirect:
+ logicalAddress, physicalAddr, err := ls.getBrokerAddress(lr)
+ if err != nil {
+ return nil, err
+ }
+
+ ls.log.Debugf("Follow topic{%s} redirect to broker. %v / %v - Use proxy: %v",
+ topic, lr.BrokerServiceUrl, lr.BrokerServiceUrlTls, lr.ProxyThroughServiceUrl)
+
+ id := ls.rpcClient.NewRequestID()
+ res, err = ls.rpcClient.Request(logicalAddress, physicalAddr, id, pb.BaseCommand_LOOKUP, &pb.CommandLookupTopic{
+ RequestId: &id,
+ Topic: &topic,
+ Authoritative: lr.Authoritative,
+ AdvertisedListenerName: proto.String(ls.listenerName),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ // Process the response at the top of the loop
+ continue
+
+ case pb.CommandLookupTopicResponse_Connect:
+ ls.log.Debugf("Successfully looked up topic{%s} on broker. %s / %s - Use proxy: %t",
+ topic, lr.GetBrokerServiceUrl(), lr.GetBrokerServiceUrlTls(), lr.GetProxyThroughServiceUrl())
+
+ logicalAddress, physicalAddress, err := ls.getBrokerAddress(lr)
+ if err != nil {
+ return nil, err
+ }
+
+ return &LookupResult{
+ LogicalAddr: logicalAddress,
+ PhysicalAddr: physicalAddress,
+ }, nil
+
+ case pb.CommandLookupTopicResponse_Failed:
+ ls.log.WithFields(log.Fields{
+ "topic": topic,
+ "error": lr.GetError(),
+ "message": lr.GetMessage(),
+ }).Warn("Failed to lookup topic")
+ return nil, errors.New(lr.GetError().String())
+ }
+ }
+
+ return nil, errors.New("exceeded max number of redirection during topic lookup")
+}
+
+func (ls *lookupService) GetPartitionedTopicMetadata(topic string) (*PartitionedTopicMetadata,
+ error) {
+ ls.metrics.PartitionedTopicMetadataRequestsCount.Inc()
+ topicName, err := ParseTopicName(topic)
+ if err != nil {
+ return nil, err
+ }
+
+ id := ls.rpcClient.NewRequestID()
+ res, err := ls.rpcClient.RequestToAnyBroker(id, pb.BaseCommand_PARTITIONED_METADATA,
+ &pb.CommandPartitionedTopicMetadata{
+ RequestId: &id,
+ Topic: &topicName.Name,
+ })
+ if err != nil {
+ return nil, err
+ }
+ ls.log.Debugf("Got topic{%s} partitioned metadata response: %+v", topic, res)
+
+ var partitionedTopicMetadata PartitionedTopicMetadata
+
+ if res.Response.Error != nil {
+ return nil, errors.New(res.Response.GetError().String())
+ }
+
+ if res.Response.PartitionMetadataResponse != nil {
+ if res.Response.PartitionMetadataResponse.Error != nil {
+ return nil, errors.New(res.Response.PartitionMetadataResponse.GetError().String())
+ }
+
+ partitionedTopicMetadata.Partitions = int(res.Response.PartitionMetadataResponse.GetPartitions())
+ } else {
+ return nil, fmt.Errorf("no partitioned metadata for topic{%s} in lookup response", topic)
+ }
+
+ return &partitionedTopicMetadata, nil
+}
+
+func (ls *lookupService) GetTopicsOfNamespace(namespace string, mode GetTopicsOfNamespaceMode) ([]string, error) {
+ id := ls.rpcClient.NewRequestID()
+ pbMode := pb.CommandGetTopicsOfNamespace_Mode(pb.CommandGetTopicsOfNamespace_Mode_value[string(mode)])
+ req := &pb.CommandGetTopicsOfNamespace{
+ RequestId: proto.Uint64(id),
+ Namespace: proto.String(namespace),
+ Mode: &pbMode,
+ }
+ res, err := ls.rpcClient.RequestToAnyBroker(id, pb.BaseCommand_GET_TOPICS_OF_NAMESPACE, req)
+ if err != nil {
+ return nil, err
+ }
+ if res.Response.Error != nil {
+ return []string{}, errors.New(res.Response.GetError().String())
+ }
+
+ return res.Response.GetTopicsOfNamespaceResponse.GetTopics(), nil
+}
+
+func (ls *lookupService) Close() {}
+
+const HTTPLookupServiceBasePathV1 string = "/lookup/v2/destination/"
+const HTTPLookupServiceBasePathV2 string = "/lookup/v2/topic/"
+const HTTPAdminServiceV1Format string = "/admin/%s/partitions"
+const HTTPAdminServiceV2Format string = "/admin/v2/%s/partitions"
+const HTTPTopicUnderNamespaceV1 string = "/admin/namespaces/%s/destinations?mode=%s"
+const HTTPTopicUnderNamespaceV2 string = "/admin/v2/namespaces/%s/topics?mode=%s"
+
+type httpLookupData struct {
+ BrokerURL string `json:"brokerUrl"`
+ BrokerURLTLS string `json:"brokerUrlTls"`
+ HTTPURL string `json:"httpUrl"`
+ HTTPURLTLS string `json:"httpUrlTls"`
+}
+
+type httpLookupService struct {
+ httpClient HTTPClient
+ serviceNameResolver ServiceNameResolver
+ tlsEnabled bool
+ log log.Logger
+ metrics *Metrics
+}
+
+func (h *httpLookupService) getBrokerAddress(ld *httpLookupData) (logicalAddress *url.URL,
+ physicalAddress *url.URL, err error) {
+ if h.tlsEnabled {
+ logicalAddress, err = url.ParseRequestURI(ld.BrokerURLTLS)
+ } else {
+ logicalAddress, err = url.ParseRequestURI(ld.BrokerURL)
+ }
+
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return logicalAddress, logicalAddress, nil
+}
+
+func (h *httpLookupService) Lookup(topic string) (*LookupResult, error) {
+ topicName, err := ParseTopicName(topic)
+ if err != nil {
+ return nil, err
+ }
+
+ basePath := HTTPLookupServiceBasePathV2
+ if !IsV2TopicName(topicName) {
+ basePath = HTTPLookupServiceBasePathV1
+ }
+
+ lookupData := &httpLookupData{}
+ err = h.httpClient.Get(basePath+GetTopicRestPath(topicName), lookupData, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ h.log.Debugf("Successfully looked up topic{%s} on http broker. %+v",
+ topic, lookupData)
+
+ logicalAddress, physicalAddress, err := h.getBrokerAddress(lookupData)
+ if err != nil {
+ return nil, err
+ }
+
+ return &LookupResult{
+ LogicalAddr: logicalAddress,
+ PhysicalAddr: physicalAddress,
+ }, nil
+
+}
+
+func (h *httpLookupService) GetPartitionedTopicMetadata(topic string) (*PartitionedTopicMetadata,
+ error) {
+ topicName, err := ParseTopicName(topic)
+ if err != nil {
+ return nil, err
+ }
+
+ format := HTTPAdminServiceV2Format
+ if !IsV2TopicName(topicName) {
+ format = HTTPAdminServiceV1Format
+ }
+
+ path := fmt.Sprintf(format, GetTopicRestPath(topicName))
+
+ tMetadata := &PartitionedTopicMetadata{}
+
+ err = h.httpClient.Get(path, tMetadata, map[string]string{"checkAllowAutoCreation": "true"})
+ if err != nil {
+ return nil, err
+ }
+
+ h.log.Debugf("Got topic{%s} partitioned metadata response: %+v", topic, tMetadata)
+
+ return tMetadata, nil
+}
+
+func (h *httpLookupService) GetTopicsOfNamespace(namespace string, mode GetTopicsOfNamespaceMode) ([]string, error) {
+
+ format := HTTPTopicUnderNamespaceV2
+ if !IsV2Namespace(namespace) {
+ format = HTTPTopicUnderNamespaceV1
+ }
+
+ path := fmt.Sprintf(format, namespace, string(mode))
+
+ topics := []string{}
+
+ err := h.httpClient.Get(path, &topics, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ h.log.Debugf("Got namespace{%s} mode{%s} topics response: %+v", namespace, mode, topics)
+
+ return topics, nil
+}
+
+func (h *httpLookupService) GetSchema(topic string, schemaVersion []byte) (schema *pb.Schema, err error) {
+ return nil, errors.New("GetSchema is not supported by httpLookupService")
+}
+func (h *httpLookupService) Close() {
+ h.httpClient.Close()
+}
+
+// NewHTTPLookupService init a http based lookup service struct and return an object of LookupService.
+func NewHTTPLookupService(httpClient HTTPClient, serviceURL *url.URL, serviceNameResolver ServiceNameResolver,
+ tlsEnabled bool, logger log.Logger, metrics *Metrics) LookupService {
+
+ return &httpLookupService{
+ httpClient: httpClient,
+ serviceNameResolver: serviceNameResolver,
+ tlsEnabled: tlsEnabled,
+ log: logger.SubLogger(log.Fields{"serviceURL": serviceURL}),
+ metrics: metrics,
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/memory_limit_controller.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/memory_limit_controller.go
new file mode 100644
index 00000000..5ead9f5b
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/memory_limit_controller.go
@@ -0,0 +1,151 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "context"
+ "sync"
+ "sync/atomic"
+)
+
+type MemoryLimitController interface {
+ ReserveMemory(ctx context.Context, size int64) bool
+ TryReserveMemory(size int64) bool
+ ForceReserveMemory(size int64)
+ ReleaseMemory(size int64)
+ CurrentUsage() int64
+ CurrentUsagePercent() float64
+ IsMemoryLimited() bool
+ RegisterTrigger(trigger func())
+}
+
+type memoryLimitController struct {
+ limit int64
+ chCond *chCond
+ currentUsage int64
+
+ triggers []*thresholdTrigger
+ // valid range is (0, 1.0)
+ triggerThreshold float64
+}
+
+type thresholdTrigger struct {
+ triggerFunc func()
+ triggerRunning int32
+}
+
+func (t *thresholdTrigger) canTryRunning() bool {
+ return atomic.CompareAndSwapInt32(&t.triggerRunning, 0, 1)
+}
+
+func (t *thresholdTrigger) setRunning(isRunning bool) {
+ if isRunning {
+ atomic.StoreInt32(&t.triggerRunning, 1)
+ } else {
+ atomic.StoreInt32(&t.triggerRunning, 0)
+ }
+}
+
+// NewMemoryLimitController threshold valid range is (0, 1.0)
+func NewMemoryLimitController(limit int64, threshold float64) MemoryLimitController {
+ mlc := &memoryLimitController{
+ limit: limit,
+ chCond: newCond(&sync.Mutex{}),
+ triggerThreshold: threshold,
+ }
+ return mlc
+}
+
+func (m *memoryLimitController) ReserveMemory(ctx context.Context, size int64) bool {
+ if !m.TryReserveMemory(size) {
+ m.chCond.L.Lock()
+ defer m.chCond.L.Unlock()
+
+ for !m.TryReserveMemory(size) {
+ if !m.chCond.waitWithContext(ctx) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+func (m *memoryLimitController) TryReserveMemory(size int64) bool {
+ for {
+ current := atomic.LoadInt64(&m.currentUsage)
+ newUsage := current + size
+
+ // This condition means we allowed one request to go over the limit.
+ if m.IsMemoryLimited() && current > m.limit {
+ return false
+ }
+
+ if atomic.CompareAndSwapInt64(&m.currentUsage, current, newUsage) {
+ m.checkTrigger(current, newUsage)
+ return true
+ }
+ }
+}
+
+func (m *memoryLimitController) ForceReserveMemory(size int64) {
+ nextUsage := atomic.AddInt64(&m.currentUsage, size)
+ prevUsage := nextUsage - size
+ m.checkTrigger(prevUsage, nextUsage)
+}
+
+func (m *memoryLimitController) ReleaseMemory(size int64) {
+ newUsage := atomic.AddInt64(&m.currentUsage, -size)
+ if newUsage+size > m.limit && newUsage <= m.limit {
+ m.chCond.broadcast()
+ }
+}
+
+func (m *memoryLimitController) CurrentUsage() int64 {
+ return atomic.LoadInt64(&m.currentUsage)
+}
+
+func (m *memoryLimitController) CurrentUsagePercent() float64 {
+ return float64(atomic.LoadInt64(&m.currentUsage)) / float64(m.limit)
+}
+
+func (m *memoryLimitController) IsMemoryLimited() bool {
+ return m.limit > 0
+}
+
+func (m *memoryLimitController) RegisterTrigger(trigger func()) {
+ m.chCond.L.Lock()
+ defer m.chCond.L.Unlock()
+ m.triggers = append(m.triggers, &thresholdTrigger{
+ triggerFunc: trigger,
+ })
+}
+
+func (m *memoryLimitController) checkTrigger(prevUsage int64, nextUsage int64) {
+ nextUsagePercent := float64(nextUsage) / float64(m.limit)
+ prevUsagePercent := float64(prevUsage) / float64(m.limit)
+ if nextUsagePercent >= m.triggerThreshold && prevUsagePercent < m.triggerThreshold {
+ for _, trigger := range m.triggers {
+ if trigger.canTryRunning() {
+ go func(trigger *thresholdTrigger) {
+ trigger.triggerFunc()
+ trigger.setRunning(false)
+ }(trigger)
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/metrics.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/metrics.go
new file mode 100644
index 00000000..e9bc8152
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/metrics.go
@@ -0,0 +1,605 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+type Metrics struct {
+ metricsLevel int
+ messagesPublished *prometheus.CounterVec
+ bytesPublished *prometheus.CounterVec
+ messagesPending *prometheus.GaugeVec
+ bytesPending *prometheus.GaugeVec
+ publishErrors *prometheus.CounterVec
+ publishLatency *prometheus.HistogramVec
+ publishRPCLatency *prometheus.HistogramVec
+
+ messagesReceived *prometheus.CounterVec
+ bytesReceived *prometheus.CounterVec
+ prefetchedMessages *prometheus.GaugeVec
+ prefetchedBytes *prometheus.GaugeVec
+ acksCounter *prometheus.CounterVec
+ nacksCounter *prometheus.CounterVec
+ dlqCounter *prometheus.CounterVec
+ processingTime *prometheus.HistogramVec
+
+ producersOpened *prometheus.CounterVec
+ producersClosed *prometheus.CounterVec
+ producersReconnectFailure *prometheus.CounterVec
+ producersReconnectMaxRetry *prometheus.CounterVec
+ producersPartitions *prometheus.GaugeVec
+ consumersOpened *prometheus.CounterVec
+ consumersClosed *prometheus.CounterVec
+ consumersReconnectFailure *prometheus.CounterVec
+ consumersReconnectMaxRetry *prometheus.CounterVec
+ consumersPartitions *prometheus.GaugeVec
+ readersOpened *prometheus.CounterVec
+ readersClosed *prometheus.CounterVec
+
+ // Metrics that are not labeled with specificity are immediately available
+ ConnectionsOpened prometheus.Counter
+ ConnectionsClosed prometheus.Counter
+ ConnectionsEstablishmentErrors prometheus.Counter
+ ConnectionsHandshakeErrors prometheus.Counter
+ LookupRequestsCount prometheus.Counter
+ PartitionedTopicMetadataRequestsCount prometheus.Counter
+ RPCRequestCount prometheus.Counter
+}
+
+type LeveledMetrics struct {
+ MessagesPublished prometheus.Counter
+ BytesPublished prometheus.Counter
+ MessagesPending prometheus.Gauge
+ BytesPending prometheus.Gauge
+ PublishErrorsTimeout prometheus.Counter
+ PublishErrorsMsgTooLarge prometheus.Counter
+ PublishLatency prometheus.Observer
+ PublishRPCLatency prometheus.Observer
+
+ MessagesReceived prometheus.Counter
+ BytesReceived prometheus.Counter
+ PrefetchedMessages prometheus.Gauge
+ PrefetchedBytes prometheus.Gauge
+ AcksCounter prometheus.Counter
+ NacksCounter prometheus.Counter
+ DlqCounter prometheus.Counter
+ ProcessingTime prometheus.Observer
+
+ ProducersOpened prometheus.Counter
+ ProducersClosed prometheus.Counter
+ ProducersReconnectFailure prometheus.Counter
+ ProducersReconnectMaxRetry prometheus.Counter
+ ProducersPartitions prometheus.Gauge
+ ConsumersOpened prometheus.Counter
+ ConsumersClosed prometheus.Counter
+ ConsumersReconnectFailure prometheus.Counter
+ ConsumersReconnectMaxRetry prometheus.Counter
+ ConsumersPartitions prometheus.Gauge
+ ReadersOpened prometheus.Counter
+ ReadersClosed prometheus.Counter
+}
+
+// NewMetricsProvider returns metrics registered to registerer.
+func NewMetricsProvider(metricsCardinality int, userDefinedLabels map[string]string,
+ registerer prometheus.Registerer) *Metrics {
+ constLabels := map[string]string{
+ "client": "go",
+ }
+ for k, v := range userDefinedLabels {
+ constLabels[k] = v
+ }
+ var metricsLevelLabels []string
+
+ // note: ints here mirror MetricsCardinality in client.go to avoid import cycle
+ switch metricsCardinality {
+ case 1: //MetricsCardinalityNone
+ metricsLevelLabels = []string{}
+ case 2: //MetricsCardinalityTenant
+ metricsLevelLabels = []string{"pulsar_tenant"}
+ case 3: //MetricsCardinalityNamespace
+ metricsLevelLabels = []string{"pulsar_tenant", "pulsar_namespace"}
+ case 4: //MetricsCardinalityTopic
+ metricsLevelLabels = []string{"pulsar_tenant", "pulsar_namespace", "topic"}
+ default: //Anything else is namespace
+ metricsLevelLabels = []string{"pulsar_tenant", "pulsar_namespace"}
+ }
+
+ metrics := &Metrics{
+ metricsLevel: metricsCardinality,
+ messagesPublished: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_messages_published",
+ Help: "Counter of messages published by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ bytesPublished: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_bytes_published",
+ Help: "Counter of messages published by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ messagesPending: prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Name: "pulsar_client_producer_pending_messages",
+ Help: "Counter of messages pending to be published by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ bytesPending: prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Name: "pulsar_client_producer_pending_bytes",
+ Help: "Counter of bytes pending to be published by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ publishErrors: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_producer_errors",
+ Help: "Counter of publish errors",
+ ConstLabels: constLabels,
+ }, append(metricsLevelLabels, "error")),
+
+ publishLatency: prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Name: "pulsar_client_producer_latency_seconds",
+ Help: "Publish latency experienced by the client",
+ ConstLabels: constLabels,
+ Buckets: []float64{.0005, .001, .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
+ }, metricsLevelLabels),
+
+ publishRPCLatency: prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Name: "pulsar_client_producer_rpc_latency_seconds",
+ Help: "Publish RPC latency experienced internally by the client when sending data to receiving an ack",
+ ConstLabels: constLabels,
+ Buckets: []float64{.0005, .001, .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
+ }, metricsLevelLabels),
+
+ producersOpened: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_producers_opened",
+ Help: "Counter of producers created by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ producersClosed: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_producers_closed",
+ Help: "Counter of producers closed by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ producersPartitions: prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Name: "pulsar_client_producers_partitions_active",
+ Help: "Counter of individual partitions the producers are currently active",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ producersReconnectFailure: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_producers_reconnect_failure",
+ Help: "Counter of reconnect failure of producers",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ producersReconnectMaxRetry: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_producers_reconnect_max_retry",
+ Help: "Counter of producer reconnect max retry reached",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ consumersOpened: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_consumers_opened",
+ Help: "Counter of consumers created by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ consumersClosed: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_consumers_closed",
+ Help: "Counter of consumers closed by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ consumersReconnectFailure: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_consumers_reconnect_failure",
+ Help: "Counter of reconnect failure of consumers",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ consumersReconnectMaxRetry: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_consumers_reconnect_max_retry",
+ Help: "Counter of consumer reconnect max retry reached",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ consumersPartitions: prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Name: "pulsar_client_consumers_partitions_active",
+ Help: "Counter of individual partitions the consumers are currently active",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ messagesReceived: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_messages_received",
+ Help: "Counter of messages received by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ bytesReceived: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_bytes_received",
+ Help: "Counter of bytes received by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ prefetchedMessages: prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Name: "pulsar_client_consumer_prefetched_messages",
+ Help: "Number of messages currently sitting in the consumer pre-fetch queue",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ prefetchedBytes: prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Name: "pulsar_client_consumer_prefetched_bytes",
+ Help: "Total number of bytes currently sitting in the consumer pre-fetch queue",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ acksCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_consumer_acks",
+ Help: "Counter of messages acked by client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ nacksCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_consumer_nacks",
+ Help: "Counter of messages nacked by client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ dlqCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_consumer_dlq_messages",
+ Help: "Counter of messages sent to Dead letter queue",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ processingTime: prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Name: "pulsar_client_consumer_processing_time_seconds",
+ Help: "Time it takes for application to process messages",
+ Buckets: []float64{.0005, .001, .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ readersOpened: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_readers_opened",
+ Help: "Counter of readers created by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ readersClosed: prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "pulsar_client_readers_closed",
+ Help: "Counter of readers closed by the client",
+ ConstLabels: constLabels,
+ }, metricsLevelLabels),
+
+ ConnectionsOpened: prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "pulsar_client_connections_opened",
+ Help: "Counter of connections created by the client",
+ ConstLabels: constLabels,
+ }),
+
+ ConnectionsClosed: prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "pulsar_client_connections_closed",
+ Help: "Counter of connections closed by the client",
+ ConstLabels: constLabels,
+ }),
+
+ ConnectionsEstablishmentErrors: prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "pulsar_client_connections_establishment_errors",
+ Help: "Counter of errors in connections establishment",
+ ConstLabels: constLabels,
+ }),
+
+ ConnectionsHandshakeErrors: prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "pulsar_client_connections_handshake_errors",
+ Help: "Counter of errors in connections handshake (eg: authz)",
+ ConstLabels: constLabels,
+ }),
+
+ LookupRequestsCount: prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "pulsar_client_lookup_count",
+ Help: "Counter of lookup requests made by the client",
+ ConstLabels: constLabels,
+ }),
+
+ PartitionedTopicMetadataRequestsCount: prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "pulsar_client_partitioned_topic_metadata_count",
+ Help: "Counter of partitioned_topic_metadata requests made by the client",
+ ConstLabels: constLabels,
+ }),
+
+ RPCRequestCount: prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "pulsar_client_rpc_count",
+ Help: "Counter of RPC requests made by the client",
+ ConstLabels: constLabels,
+ }),
+ }
+
+ err := registerer.Register(metrics.messagesPublished)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.messagesPublished = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.bytesPublished)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.bytesPublished = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.messagesPending)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.messagesPending = are.ExistingCollector.(*prometheus.GaugeVec)
+ }
+ }
+ err = registerer.Register(metrics.bytesPending)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.bytesPending = are.ExistingCollector.(*prometheus.GaugeVec)
+ }
+ }
+ err = registerer.Register(metrics.publishErrors)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.publishErrors = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.publishLatency)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.publishLatency = are.ExistingCollector.(*prometheus.HistogramVec)
+ }
+ }
+ err = registerer.Register(metrics.publishRPCLatency)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.publishRPCLatency = are.ExistingCollector.(*prometheus.HistogramVec)
+ }
+ }
+ err = registerer.Register(metrics.messagesReceived)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.messagesReceived = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.bytesReceived)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.bytesReceived = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.prefetchedMessages)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.prefetchedMessages = are.ExistingCollector.(*prometheus.GaugeVec)
+ }
+ }
+ err = registerer.Register(metrics.prefetchedBytes)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.prefetchedBytes = are.ExistingCollector.(*prometheus.GaugeVec)
+ }
+ }
+ err = registerer.Register(metrics.acksCounter)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.acksCounter = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.nacksCounter)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.nacksCounter = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.dlqCounter)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.dlqCounter = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.processingTime)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.processingTime = are.ExistingCollector.(*prometheus.HistogramVec)
+ }
+ }
+ err = registerer.Register(metrics.producersOpened)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.producersOpened = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.producersClosed)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.producersClosed = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.producersReconnectFailure)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.producersReconnectFailure = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.producersReconnectMaxRetry)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.producersReconnectMaxRetry = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.producersPartitions)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.producersPartitions = are.ExistingCollector.(*prometheus.GaugeVec)
+ }
+ }
+ err = registerer.Register(metrics.consumersOpened)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.consumersOpened = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.consumersClosed)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.consumersClosed = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.consumersReconnectFailure)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.consumersReconnectFailure = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.consumersReconnectMaxRetry)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.consumersReconnectMaxRetry = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.consumersPartitions)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.consumersPartitions = are.ExistingCollector.(*prometheus.GaugeVec)
+ }
+ }
+ err = registerer.Register(metrics.readersOpened)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.readersOpened = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.readersClosed)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.readersClosed = are.ExistingCollector.(*prometheus.CounterVec)
+ }
+ }
+ err = registerer.Register(metrics.ConnectionsOpened)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.ConnectionsOpened = are.ExistingCollector.(prometheus.Counter)
+ }
+ }
+ err = registerer.Register(metrics.ConnectionsClosed)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.ConnectionsClosed = are.ExistingCollector.(prometheus.Counter)
+ }
+ }
+ err = registerer.Register(metrics.ConnectionsEstablishmentErrors)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.ConnectionsEstablishmentErrors = are.ExistingCollector.(prometheus.Counter)
+ }
+ }
+ err = registerer.Register(metrics.ConnectionsHandshakeErrors)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.ConnectionsHandshakeErrors = are.ExistingCollector.(prometheus.Counter)
+ }
+ }
+ err = registerer.Register(metrics.LookupRequestsCount)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.LookupRequestsCount = are.ExistingCollector.(prometheus.Counter)
+ }
+ }
+ err = registerer.Register(metrics.PartitionedTopicMetadataRequestsCount)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.PartitionedTopicMetadataRequestsCount = are.ExistingCollector.(prometheus.Counter)
+ }
+ }
+ err = registerer.Register(metrics.RPCRequestCount)
+ if err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ metrics.RPCRequestCount = are.ExistingCollector.(prometheus.Counter)
+ }
+ }
+ return metrics
+}
+
+func (mp *Metrics) GetLeveledMetrics(t string) *LeveledMetrics {
+ labels := make(map[string]string, 3)
+ tn, err := ParseTopicName(t)
+ if err != nil {
+ return nil
+ }
+ topic := TopicNameWithoutPartitionPart(tn)
+ switch mp.metricsLevel {
+ case 4:
+ labels["topic"] = topic
+ fallthrough
+ case 3:
+ labels["pulsar_namespace"] = tn.Namespace
+ fallthrough
+ case 2:
+ labels["pulsar_tenant"] = tn.Tenant
+ }
+
+ lm := &LeveledMetrics{
+ MessagesPublished: mp.messagesPublished.With(labels),
+ BytesPublished: mp.bytesPublished.With(labels),
+ MessagesPending: mp.messagesPending.With(labels),
+ BytesPending: mp.bytesPending.With(labels),
+ PublishErrorsTimeout: mp.publishErrors.With(mergeMaps(labels, map[string]string{"error": "timeout"})),
+ PublishErrorsMsgTooLarge: mp.publishErrors.With(mergeMaps(labels, map[string]string{"error": "msg_too_large"})),
+ PublishLatency: mp.publishLatency.With(labels),
+ PublishRPCLatency: mp.publishRPCLatency.With(labels),
+
+ MessagesReceived: mp.messagesReceived.With(labels),
+ BytesReceived: mp.bytesReceived.With(labels),
+ PrefetchedMessages: mp.prefetchedMessages.With(labels),
+ PrefetchedBytes: mp.prefetchedBytes.With(labels),
+ AcksCounter: mp.acksCounter.With(labels),
+ NacksCounter: mp.nacksCounter.With(labels),
+ DlqCounter: mp.dlqCounter.With(labels),
+ ProcessingTime: mp.processingTime.With(labels),
+
+ ProducersOpened: mp.producersOpened.With(labels),
+ ProducersClosed: mp.producersClosed.With(labels),
+ ProducersReconnectFailure: mp.producersReconnectFailure.With(labels),
+ ProducersReconnectMaxRetry: mp.producersReconnectMaxRetry.With(labels),
+ ProducersPartitions: mp.producersPartitions.With(labels),
+ ConsumersOpened: mp.consumersOpened.With(labels),
+ ConsumersClosed: mp.consumersClosed.With(labels),
+ ConsumersReconnectFailure: mp.consumersReconnectFailure.With(labels),
+ ConsumersReconnectMaxRetry: mp.consumersReconnectMaxRetry.With(labels),
+ ConsumersPartitions: mp.consumersPartitions.With(labels),
+ ReadersOpened: mp.readersOpened.With(labels),
+ ReadersClosed: mp.readersClosed.With(labels),
+ }
+
+ return lm
+}
+
+func mergeMaps(a, b map[string]string) map[string]string {
+ res := make(map[string]string)
+ for k, v := range a {
+ res[k] = v
+ }
+ for k, v := range b {
+ res[k] = v
+ }
+
+ return res
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/namespace_name.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/namespace_name.go
new file mode 100644
index 00000000..5e9fee22
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/namespace_name.go
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import "strings"
+
+func IsV2Namespace(namespace string) bool {
+ parts := strings.Split(namespace, "/")
+ // Legacy namespace name that includes cluster name
+ return len(parts) == 2
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/PulsarApi.pb.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/PulsarApi.pb.go
new file mode 100644
index 00000000..c8e6ad9b
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/PulsarApi.pb.go
@@ -0,0 +1,10216 @@
+//*
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.1
+// protoc v3.21.9
+// source: PulsarApi.proto
+
+package proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type CompressionType int32
+
+const (
+ CompressionType_NONE CompressionType = 0
+ CompressionType_LZ4 CompressionType = 1
+ CompressionType_ZLIB CompressionType = 2
+ CompressionType_ZSTD CompressionType = 3
+ CompressionType_SNAPPY CompressionType = 4
+)
+
+// Enum value maps for CompressionType.
+var (
+ CompressionType_name = map[int32]string{
+ 0: "NONE",
+ 1: "LZ4",
+ 2: "ZLIB",
+ 3: "ZSTD",
+ 4: "SNAPPY",
+ }
+ CompressionType_value = map[string]int32{
+ "NONE": 0,
+ "LZ4": 1,
+ "ZLIB": 2,
+ "ZSTD": 3,
+ "SNAPPY": 4,
+ }
+)
+
+func (x CompressionType) Enum() *CompressionType {
+ p := new(CompressionType)
+ *p = x
+ return p
+}
+
+func (x CompressionType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CompressionType) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[0].Descriptor()
+}
+
+func (CompressionType) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[0]
+}
+
+func (x CompressionType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CompressionType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CompressionType(num)
+ return nil
+}
+
+// Deprecated: Use CompressionType.Descriptor instead.
+func (CompressionType) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{0}
+}
+
+type ProducerAccessMode int32
+
+const (
+ ProducerAccessMode_Shared ProducerAccessMode = 0 // By default multiple producers can publish on a topic
+ ProducerAccessMode_Exclusive ProducerAccessMode = 1 // Require exclusive access for producer. Fail immediately if there's already a producer connected.
+ ProducerAccessMode_WaitForExclusive ProducerAccessMode = 2 // Producer creation is pending until it can acquire exclusive access
+ ProducerAccessMode_ExclusiveWithFencing ProducerAccessMode = 3 // Require exclusive access for producer. Fence out old producer.
+)
+
+// Enum value maps for ProducerAccessMode.
+var (
+ ProducerAccessMode_name = map[int32]string{
+ 0: "Shared",
+ 1: "Exclusive",
+ 2: "WaitForExclusive",
+ 3: "ExclusiveWithFencing",
+ }
+ ProducerAccessMode_value = map[string]int32{
+ "Shared": 0,
+ "Exclusive": 1,
+ "WaitForExclusive": 2,
+ "ExclusiveWithFencing": 3,
+ }
+)
+
+func (x ProducerAccessMode) Enum() *ProducerAccessMode {
+ p := new(ProducerAccessMode)
+ *p = x
+ return p
+}
+
+func (x ProducerAccessMode) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ProducerAccessMode) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[1].Descriptor()
+}
+
+func (ProducerAccessMode) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[1]
+}
+
+func (x ProducerAccessMode) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *ProducerAccessMode) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = ProducerAccessMode(num)
+ return nil
+}
+
+// Deprecated: Use ProducerAccessMode.Descriptor instead.
+func (ProducerAccessMode) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{1}
+}
+
+type ServerError int32
+
+const (
+ ServerError_UnknownError ServerError = 0
+ ServerError_MetadataError ServerError = 1 // Error with ZK/metadata
+ ServerError_PersistenceError ServerError = 2 // Error writing reading from BK
+ ServerError_AuthenticationError ServerError = 3 // Non valid authentication
+ ServerError_AuthorizationError ServerError = 4 // Not authorized to use resource
+ ServerError_ConsumerBusy ServerError = 5 // Unable to subscribe/unsubscribe because
+ // other consumers are connected
+ ServerError_ServiceNotReady ServerError = 6 // Any error that requires client retry operation with a fresh lookup
+ ServerError_ProducerBlockedQuotaExceededError ServerError = 7 // Unable to create producer because backlog quota exceeded
+ ServerError_ProducerBlockedQuotaExceededException ServerError = 8 // Exception while creating producer because quota exceeded
+ ServerError_ChecksumError ServerError = 9 // Error while verifying message checksum
+ ServerError_UnsupportedVersionError ServerError = 10 // Error when an older client/version doesn't support a required feature
+ ServerError_TopicNotFound ServerError = 11 // Topic not found
+ ServerError_SubscriptionNotFound ServerError = 12 // Subscription not found
+ ServerError_ConsumerNotFound ServerError = 13 // Consumer not found
+ ServerError_TooManyRequests ServerError = 14 // Error with too many simultaneously request
+ ServerError_TopicTerminatedError ServerError = 15 // The topic has been terminated
+ ServerError_ProducerBusy ServerError = 16 // Producer with same name is already connected
+ ServerError_InvalidTopicName ServerError = 17 // The topic name is not valid
+ ServerError_IncompatibleSchema ServerError = 18 // Specified schema was incompatible with topic schema
+ ServerError_ConsumerAssignError ServerError = 19 // Dispatcher assign consumer error
+ ServerError_TransactionCoordinatorNotFound ServerError = 20 // Transaction coordinator not found error
+ ServerError_InvalidTxnStatus ServerError = 21 // Invalid txn status error
+ ServerError_NotAllowedError ServerError = 22 // Not allowed error
+ ServerError_TransactionConflict ServerError = 23 // Ack with transaction conflict
+ ServerError_TransactionNotFound ServerError = 24 // Transaction not found
+ ServerError_ProducerFenced ServerError = 25 // When a producer asks and fail to get exclusive producer access,
+)
+
+// Enum value maps for ServerError.
+var (
+ ServerError_name = map[int32]string{
+ 0: "UnknownError",
+ 1: "MetadataError",
+ 2: "PersistenceError",
+ 3: "AuthenticationError",
+ 4: "AuthorizationError",
+ 5: "ConsumerBusy",
+ 6: "ServiceNotReady",
+ 7: "ProducerBlockedQuotaExceededError",
+ 8: "ProducerBlockedQuotaExceededException",
+ 9: "ChecksumError",
+ 10: "UnsupportedVersionError",
+ 11: "TopicNotFound",
+ 12: "SubscriptionNotFound",
+ 13: "ConsumerNotFound",
+ 14: "TooManyRequests",
+ 15: "TopicTerminatedError",
+ 16: "ProducerBusy",
+ 17: "InvalidTopicName",
+ 18: "IncompatibleSchema",
+ 19: "ConsumerAssignError",
+ 20: "TransactionCoordinatorNotFound",
+ 21: "InvalidTxnStatus",
+ 22: "NotAllowedError",
+ 23: "TransactionConflict",
+ 24: "TransactionNotFound",
+ 25: "ProducerFenced",
+ }
+ ServerError_value = map[string]int32{
+ "UnknownError": 0,
+ "MetadataError": 1,
+ "PersistenceError": 2,
+ "AuthenticationError": 3,
+ "AuthorizationError": 4,
+ "ConsumerBusy": 5,
+ "ServiceNotReady": 6,
+ "ProducerBlockedQuotaExceededError": 7,
+ "ProducerBlockedQuotaExceededException": 8,
+ "ChecksumError": 9,
+ "UnsupportedVersionError": 10,
+ "TopicNotFound": 11,
+ "SubscriptionNotFound": 12,
+ "ConsumerNotFound": 13,
+ "TooManyRequests": 14,
+ "TopicTerminatedError": 15,
+ "ProducerBusy": 16,
+ "InvalidTopicName": 17,
+ "IncompatibleSchema": 18,
+ "ConsumerAssignError": 19,
+ "TransactionCoordinatorNotFound": 20,
+ "InvalidTxnStatus": 21,
+ "NotAllowedError": 22,
+ "TransactionConflict": 23,
+ "TransactionNotFound": 24,
+ "ProducerFenced": 25,
+ }
+)
+
+func (x ServerError) Enum() *ServerError {
+ p := new(ServerError)
+ *p = x
+ return p
+}
+
+func (x ServerError) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ServerError) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[2].Descriptor()
+}
+
+func (ServerError) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[2]
+}
+
+func (x ServerError) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *ServerError) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = ServerError(num)
+ return nil
+}
+
+// Deprecated: Use ServerError.Descriptor instead.
+func (ServerError) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{2}
+}
+
+type AuthMethod int32
+
+const (
+ AuthMethod_AuthMethodNone AuthMethod = 0
+ AuthMethod_AuthMethodYcaV1 AuthMethod = 1
+ AuthMethod_AuthMethodAthens AuthMethod = 2
+)
+
+// Enum value maps for AuthMethod.
+var (
+ AuthMethod_name = map[int32]string{
+ 0: "AuthMethodNone",
+ 1: "AuthMethodYcaV1",
+ 2: "AuthMethodAthens",
+ }
+ AuthMethod_value = map[string]int32{
+ "AuthMethodNone": 0,
+ "AuthMethodYcaV1": 1,
+ "AuthMethodAthens": 2,
+ }
+)
+
+func (x AuthMethod) Enum() *AuthMethod {
+ p := new(AuthMethod)
+ *p = x
+ return p
+}
+
+func (x AuthMethod) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (AuthMethod) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[3].Descriptor()
+}
+
+func (AuthMethod) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[3]
+}
+
+func (x AuthMethod) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *AuthMethod) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = AuthMethod(num)
+ return nil
+}
+
+// Deprecated: Use AuthMethod.Descriptor instead.
+func (AuthMethod) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{3}
+}
+
+// Each protocol version identify new features that are
+// incrementally added to the protocol
+type ProtocolVersion int32
+
+const (
+ ProtocolVersion_v0 ProtocolVersion = 0 // Initial versioning
+ ProtocolVersion_v1 ProtocolVersion = 1 // Added application keep-alive
+ ProtocolVersion_v2 ProtocolVersion = 2 // Added RedeliverUnacknowledgedMessages Command
+ ProtocolVersion_v3 ProtocolVersion = 3 // Added compression with LZ4 and ZLib
+ ProtocolVersion_v4 ProtocolVersion = 4 // Added batch message support
+ ProtocolVersion_v5 ProtocolVersion = 5 // Added disconnect client w/o closing connection
+ ProtocolVersion_v6 ProtocolVersion = 6 // Added checksum computation for metadata + payload
+ ProtocolVersion_v7 ProtocolVersion = 7 // Added CommandLookupTopic - Binary Lookup
+ ProtocolVersion_v8 ProtocolVersion = 8 // Added CommandConsumerStats - Client fetches broker side consumer stats
+ ProtocolVersion_v9 ProtocolVersion = 9 // Added end of topic notification
+ ProtocolVersion_v10 ProtocolVersion = 10 // Added proxy to broker
+ ProtocolVersion_v11 ProtocolVersion = 11 // C++ consumers before this version are not correctly handling the checksum field
+ ProtocolVersion_v12 ProtocolVersion = 12 // Added get topic's last messageId from broker
+ // Added CommandActiveConsumerChange
+ // Added CommandGetTopicsOfNamespace
+ ProtocolVersion_v13 ProtocolVersion = 13 // Schema-registry : added avro schema format for json
+ ProtocolVersion_v14 ProtocolVersion = 14 // Add CommandAuthChallenge and CommandAuthResponse for mutual auth
+ // Added Key_Shared subscription
+ ProtocolVersion_v15 ProtocolVersion = 15 // Add CommandGetOrCreateSchema and CommandGetOrCreateSchemaResponse
+ ProtocolVersion_v16 ProtocolVersion = 16 // Add support for broker entry metadata
+ ProtocolVersion_v17 ProtocolVersion = 17 // Added support ack receipt
+ ProtocolVersion_v18 ProtocolVersion = 18 // Add client support for broker entry metadata
+ ProtocolVersion_v19 ProtocolVersion = 19 // Add CommandTcClientConnectRequest and CommandTcClientConnectResponse
+)
+
+// Enum value maps for ProtocolVersion.
+var (
+ ProtocolVersion_name = map[int32]string{
+ 0: "v0",
+ 1: "v1",
+ 2: "v2",
+ 3: "v3",
+ 4: "v4",
+ 5: "v5",
+ 6: "v6",
+ 7: "v7",
+ 8: "v8",
+ 9: "v9",
+ 10: "v10",
+ 11: "v11",
+ 12: "v12",
+ 13: "v13",
+ 14: "v14",
+ 15: "v15",
+ 16: "v16",
+ 17: "v17",
+ 18: "v18",
+ 19: "v19",
+ }
+ ProtocolVersion_value = map[string]int32{
+ "v0": 0,
+ "v1": 1,
+ "v2": 2,
+ "v3": 3,
+ "v4": 4,
+ "v5": 5,
+ "v6": 6,
+ "v7": 7,
+ "v8": 8,
+ "v9": 9,
+ "v10": 10,
+ "v11": 11,
+ "v12": 12,
+ "v13": 13,
+ "v14": 14,
+ "v15": 15,
+ "v16": 16,
+ "v17": 17,
+ "v18": 18,
+ "v19": 19,
+ }
+)
+
+func (x ProtocolVersion) Enum() *ProtocolVersion {
+ p := new(ProtocolVersion)
+ *p = x
+ return p
+}
+
+func (x ProtocolVersion) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ProtocolVersion) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[4].Descriptor()
+}
+
+func (ProtocolVersion) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[4]
+}
+
+func (x ProtocolVersion) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *ProtocolVersion) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = ProtocolVersion(num)
+ return nil
+}
+
+// Deprecated: Use ProtocolVersion.Descriptor instead.
+func (ProtocolVersion) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{4}
+}
+
+type KeySharedMode int32
+
+const (
+ KeySharedMode_AUTO_SPLIT KeySharedMode = 0
+ KeySharedMode_STICKY KeySharedMode = 1
+)
+
+// Enum value maps for KeySharedMode.
+var (
+ KeySharedMode_name = map[int32]string{
+ 0: "AUTO_SPLIT",
+ 1: "STICKY",
+ }
+ KeySharedMode_value = map[string]int32{
+ "AUTO_SPLIT": 0,
+ "STICKY": 1,
+ }
+)
+
+func (x KeySharedMode) Enum() *KeySharedMode {
+ p := new(KeySharedMode)
+ *p = x
+ return p
+}
+
+func (x KeySharedMode) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (KeySharedMode) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[5].Descriptor()
+}
+
+func (KeySharedMode) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[5]
+}
+
+func (x KeySharedMode) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *KeySharedMode) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = KeySharedMode(num)
+ return nil
+}
+
+// Deprecated: Use KeySharedMode.Descriptor instead.
+func (KeySharedMode) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{5}
+}
+
+type TxnAction int32
+
+const (
+ TxnAction_COMMIT TxnAction = 0
+ TxnAction_ABORT TxnAction = 1
+)
+
+// Enum value maps for TxnAction.
+var (
+ TxnAction_name = map[int32]string{
+ 0: "COMMIT",
+ 1: "ABORT",
+ }
+ TxnAction_value = map[string]int32{
+ "COMMIT": 0,
+ "ABORT": 1,
+ }
+)
+
+func (x TxnAction) Enum() *TxnAction {
+ p := new(TxnAction)
+ *p = x
+ return p
+}
+
+func (x TxnAction) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (TxnAction) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[6].Descriptor()
+}
+
+func (TxnAction) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[6]
+}
+
+func (x TxnAction) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *TxnAction) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = TxnAction(num)
+ return nil
+}
+
+// Deprecated: Use TxnAction.Descriptor instead.
+func (TxnAction) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{6}
+}
+
+type Schema_Type int32
+
+const (
+ Schema_None Schema_Type = 0
+ Schema_String Schema_Type = 1
+ Schema_Json Schema_Type = 2
+ Schema_Protobuf Schema_Type = 3
+ Schema_Avro Schema_Type = 4
+ Schema_Bool Schema_Type = 5
+ Schema_Int8 Schema_Type = 6
+ Schema_Int16 Schema_Type = 7
+ Schema_Int32 Schema_Type = 8
+ Schema_Int64 Schema_Type = 9
+ Schema_Float Schema_Type = 10
+ Schema_Double Schema_Type = 11
+ Schema_Date Schema_Type = 12
+ Schema_Time Schema_Type = 13
+ Schema_Timestamp Schema_Type = 14
+ Schema_KeyValue Schema_Type = 15
+ Schema_Instant Schema_Type = 16
+ Schema_LocalDate Schema_Type = 17
+ Schema_LocalTime Schema_Type = 18
+ Schema_LocalDateTime Schema_Type = 19
+ Schema_ProtobufNative Schema_Type = 20
+)
+
+// Enum value maps for Schema_Type.
+var (
+ Schema_Type_name = map[int32]string{
+ 0: "None",
+ 1: "String",
+ 2: "Json",
+ 3: "Protobuf",
+ 4: "Avro",
+ 5: "Bool",
+ 6: "Int8",
+ 7: "Int16",
+ 8: "Int32",
+ 9: "Int64",
+ 10: "Float",
+ 11: "Double",
+ 12: "Date",
+ 13: "Time",
+ 14: "Timestamp",
+ 15: "KeyValue",
+ 16: "Instant",
+ 17: "LocalDate",
+ 18: "LocalTime",
+ 19: "LocalDateTime",
+ 20: "ProtobufNative",
+ }
+ Schema_Type_value = map[string]int32{
+ "None": 0,
+ "String": 1,
+ "Json": 2,
+ "Protobuf": 3,
+ "Avro": 4,
+ "Bool": 5,
+ "Int8": 6,
+ "Int16": 7,
+ "Int32": 8,
+ "Int64": 9,
+ "Float": 10,
+ "Double": 11,
+ "Date": 12,
+ "Time": 13,
+ "Timestamp": 14,
+ "KeyValue": 15,
+ "Instant": 16,
+ "LocalDate": 17,
+ "LocalTime": 18,
+ "LocalDateTime": 19,
+ "ProtobufNative": 20,
+ }
+)
+
+func (x Schema_Type) Enum() *Schema_Type {
+ p := new(Schema_Type)
+ *p = x
+ return p
+}
+
+func (x Schema_Type) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Schema_Type) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[7].Descriptor()
+}
+
+func (Schema_Type) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[7]
+}
+
+func (x Schema_Type) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *Schema_Type) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = Schema_Type(num)
+ return nil
+}
+
+// Deprecated: Use Schema_Type.Descriptor instead.
+func (Schema_Type) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{0, 0}
+}
+
+type CommandSubscribe_SubType int32
+
+const (
+ CommandSubscribe_Exclusive CommandSubscribe_SubType = 0
+ CommandSubscribe_Shared CommandSubscribe_SubType = 1
+ CommandSubscribe_Failover CommandSubscribe_SubType = 2
+ CommandSubscribe_Key_Shared CommandSubscribe_SubType = 3
+)
+
+// Enum value maps for CommandSubscribe_SubType.
+var (
+ CommandSubscribe_SubType_name = map[int32]string{
+ 0: "Exclusive",
+ 1: "Shared",
+ 2: "Failover",
+ 3: "Key_Shared",
+ }
+ CommandSubscribe_SubType_value = map[string]int32{
+ "Exclusive": 0,
+ "Shared": 1,
+ "Failover": 2,
+ "Key_Shared": 3,
+ }
+)
+
+func (x CommandSubscribe_SubType) Enum() *CommandSubscribe_SubType {
+ p := new(CommandSubscribe_SubType)
+ *p = x
+ return p
+}
+
+func (x CommandSubscribe_SubType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CommandSubscribe_SubType) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[8].Descriptor()
+}
+
+func (CommandSubscribe_SubType) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[8]
+}
+
+func (x CommandSubscribe_SubType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CommandSubscribe_SubType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CommandSubscribe_SubType(num)
+ return nil
+}
+
+// Deprecated: Use CommandSubscribe_SubType.Descriptor instead.
+func (CommandSubscribe_SubType) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{16, 0}
+}
+
+type CommandSubscribe_InitialPosition int32
+
+const (
+ CommandSubscribe_Latest CommandSubscribe_InitialPosition = 0
+ CommandSubscribe_Earliest CommandSubscribe_InitialPosition = 1
+)
+
+// Enum value maps for CommandSubscribe_InitialPosition.
+var (
+ CommandSubscribe_InitialPosition_name = map[int32]string{
+ 0: "Latest",
+ 1: "Earliest",
+ }
+ CommandSubscribe_InitialPosition_value = map[string]int32{
+ "Latest": 0,
+ "Earliest": 1,
+ }
+)
+
+func (x CommandSubscribe_InitialPosition) Enum() *CommandSubscribe_InitialPosition {
+ p := new(CommandSubscribe_InitialPosition)
+ *p = x
+ return p
+}
+
+func (x CommandSubscribe_InitialPosition) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CommandSubscribe_InitialPosition) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[9].Descriptor()
+}
+
+func (CommandSubscribe_InitialPosition) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[9]
+}
+
+func (x CommandSubscribe_InitialPosition) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CommandSubscribe_InitialPosition) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CommandSubscribe_InitialPosition(num)
+ return nil
+}
+
+// Deprecated: Use CommandSubscribe_InitialPosition.Descriptor instead.
+func (CommandSubscribe_InitialPosition) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{16, 1}
+}
+
+type CommandPartitionedTopicMetadataResponse_LookupType int32
+
+const (
+ CommandPartitionedTopicMetadataResponse_Success CommandPartitionedTopicMetadataResponse_LookupType = 0
+ CommandPartitionedTopicMetadataResponse_Failed CommandPartitionedTopicMetadataResponse_LookupType = 1
+)
+
+// Enum value maps for CommandPartitionedTopicMetadataResponse_LookupType.
+var (
+ CommandPartitionedTopicMetadataResponse_LookupType_name = map[int32]string{
+ 0: "Success",
+ 1: "Failed",
+ }
+ CommandPartitionedTopicMetadataResponse_LookupType_value = map[string]int32{
+ "Success": 0,
+ "Failed": 1,
+ }
+)
+
+func (x CommandPartitionedTopicMetadataResponse_LookupType) Enum() *CommandPartitionedTopicMetadataResponse_LookupType {
+ p := new(CommandPartitionedTopicMetadataResponse_LookupType)
+ *p = x
+ return p
+}
+
+func (x CommandPartitionedTopicMetadataResponse_LookupType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CommandPartitionedTopicMetadataResponse_LookupType) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[10].Descriptor()
+}
+
+func (CommandPartitionedTopicMetadataResponse_LookupType) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[10]
+}
+
+func (x CommandPartitionedTopicMetadataResponse_LookupType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CommandPartitionedTopicMetadataResponse_LookupType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CommandPartitionedTopicMetadataResponse_LookupType(num)
+ return nil
+}
+
+// Deprecated: Use CommandPartitionedTopicMetadataResponse_LookupType.Descriptor instead.
+func (CommandPartitionedTopicMetadataResponse_LookupType) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{18, 0}
+}
+
+type CommandLookupTopicResponse_LookupType int32
+
+const (
+ CommandLookupTopicResponse_Redirect CommandLookupTopicResponse_LookupType = 0
+ CommandLookupTopicResponse_Connect CommandLookupTopicResponse_LookupType = 1
+ CommandLookupTopicResponse_Failed CommandLookupTopicResponse_LookupType = 2
+)
+
+// Enum value maps for CommandLookupTopicResponse_LookupType.
+var (
+ CommandLookupTopicResponse_LookupType_name = map[int32]string{
+ 0: "Redirect",
+ 1: "Connect",
+ 2: "Failed",
+ }
+ CommandLookupTopicResponse_LookupType_value = map[string]int32{
+ "Redirect": 0,
+ "Connect": 1,
+ "Failed": 2,
+ }
+)
+
+func (x CommandLookupTopicResponse_LookupType) Enum() *CommandLookupTopicResponse_LookupType {
+ p := new(CommandLookupTopicResponse_LookupType)
+ *p = x
+ return p
+}
+
+func (x CommandLookupTopicResponse_LookupType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CommandLookupTopicResponse_LookupType) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[11].Descriptor()
+}
+
+func (CommandLookupTopicResponse_LookupType) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[11]
+}
+
+func (x CommandLookupTopicResponse_LookupType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CommandLookupTopicResponse_LookupType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CommandLookupTopicResponse_LookupType(num)
+ return nil
+}
+
+// Deprecated: Use CommandLookupTopicResponse_LookupType.Descriptor instead.
+func (CommandLookupTopicResponse_LookupType) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{20, 0}
+}
+
+type CommandAck_AckType int32
+
+const (
+ CommandAck_Individual CommandAck_AckType = 0
+ CommandAck_Cumulative CommandAck_AckType = 1
+)
+
+// Enum value maps for CommandAck_AckType.
+var (
+ CommandAck_AckType_name = map[int32]string{
+ 0: "Individual",
+ 1: "Cumulative",
+ }
+ CommandAck_AckType_value = map[string]int32{
+ "Individual": 0,
+ "Cumulative": 1,
+ }
+)
+
+func (x CommandAck_AckType) Enum() *CommandAck_AckType {
+ p := new(CommandAck_AckType)
+ *p = x
+ return p
+}
+
+func (x CommandAck_AckType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CommandAck_AckType) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[12].Descriptor()
+}
+
+func (CommandAck_AckType) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[12]
+}
+
+func (x CommandAck_AckType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CommandAck_AckType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CommandAck_AckType(num)
+ return nil
+}
+
+// Deprecated: Use CommandAck_AckType.Descriptor instead.
+func (CommandAck_AckType) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{26, 0}
+}
+
+// Acks can contain a flag to indicate the consumer
+// received an invalid message that got discarded
+// before being passed on to the application.
+type CommandAck_ValidationError int32
+
+const (
+ CommandAck_UncompressedSizeCorruption CommandAck_ValidationError = 0
+ CommandAck_DecompressionError CommandAck_ValidationError = 1
+ CommandAck_ChecksumMismatch CommandAck_ValidationError = 2
+ CommandAck_BatchDeSerializeError CommandAck_ValidationError = 3
+ CommandAck_DecryptionError CommandAck_ValidationError = 4
+)
+
+// Enum value maps for CommandAck_ValidationError.
+var (
+ CommandAck_ValidationError_name = map[int32]string{
+ 0: "UncompressedSizeCorruption",
+ 1: "DecompressionError",
+ 2: "ChecksumMismatch",
+ 3: "BatchDeSerializeError",
+ 4: "DecryptionError",
+ }
+ CommandAck_ValidationError_value = map[string]int32{
+ "UncompressedSizeCorruption": 0,
+ "DecompressionError": 1,
+ "ChecksumMismatch": 2,
+ "BatchDeSerializeError": 3,
+ "DecryptionError": 4,
+ }
+)
+
+func (x CommandAck_ValidationError) Enum() *CommandAck_ValidationError {
+ p := new(CommandAck_ValidationError)
+ *p = x
+ return p
+}
+
+func (x CommandAck_ValidationError) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CommandAck_ValidationError) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[13].Descriptor()
+}
+
+func (CommandAck_ValidationError) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[13]
+}
+
+func (x CommandAck_ValidationError) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CommandAck_ValidationError) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CommandAck_ValidationError(num)
+ return nil
+}
+
+// Deprecated: Use CommandAck_ValidationError.Descriptor instead.
+func (CommandAck_ValidationError) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{26, 1}
+}
+
+type CommandGetTopicsOfNamespace_Mode int32
+
+const (
+ CommandGetTopicsOfNamespace_PERSISTENT CommandGetTopicsOfNamespace_Mode = 0
+ CommandGetTopicsOfNamespace_NON_PERSISTENT CommandGetTopicsOfNamespace_Mode = 1
+ CommandGetTopicsOfNamespace_ALL CommandGetTopicsOfNamespace_Mode = 2
+)
+
+// Enum value maps for CommandGetTopicsOfNamespace_Mode.
+var (
+ CommandGetTopicsOfNamespace_Mode_name = map[int32]string{
+ 0: "PERSISTENT",
+ 1: "NON_PERSISTENT",
+ 2: "ALL",
+ }
+ CommandGetTopicsOfNamespace_Mode_value = map[string]int32{
+ "PERSISTENT": 0,
+ "NON_PERSISTENT": 1,
+ "ALL": 2,
+ }
+)
+
+func (x CommandGetTopicsOfNamespace_Mode) Enum() *CommandGetTopicsOfNamespace_Mode {
+ p := new(CommandGetTopicsOfNamespace_Mode)
+ *p = x
+ return p
+}
+
+func (x CommandGetTopicsOfNamespace_Mode) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (CommandGetTopicsOfNamespace_Mode) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[14].Descriptor()
+}
+
+func (CommandGetTopicsOfNamespace_Mode) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[14]
+}
+
+func (x CommandGetTopicsOfNamespace_Mode) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *CommandGetTopicsOfNamespace_Mode) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = CommandGetTopicsOfNamespace_Mode(num)
+ return nil
+}
+
+// Deprecated: Use CommandGetTopicsOfNamespace_Mode.Descriptor instead.
+func (CommandGetTopicsOfNamespace_Mode) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{45, 0}
+}
+
+type BaseCommand_Type int32
+
+const (
+ BaseCommand_CONNECT BaseCommand_Type = 2
+ BaseCommand_CONNECTED BaseCommand_Type = 3
+ BaseCommand_SUBSCRIBE BaseCommand_Type = 4
+ BaseCommand_PRODUCER BaseCommand_Type = 5
+ BaseCommand_SEND BaseCommand_Type = 6
+ BaseCommand_SEND_RECEIPT BaseCommand_Type = 7
+ BaseCommand_SEND_ERROR BaseCommand_Type = 8
+ BaseCommand_MESSAGE BaseCommand_Type = 9
+ BaseCommand_ACK BaseCommand_Type = 10
+ BaseCommand_FLOW BaseCommand_Type = 11
+ BaseCommand_UNSUBSCRIBE BaseCommand_Type = 12
+ BaseCommand_SUCCESS BaseCommand_Type = 13
+ BaseCommand_ERROR BaseCommand_Type = 14
+ BaseCommand_CLOSE_PRODUCER BaseCommand_Type = 15
+ BaseCommand_CLOSE_CONSUMER BaseCommand_Type = 16
+ BaseCommand_PRODUCER_SUCCESS BaseCommand_Type = 17
+ BaseCommand_PING BaseCommand_Type = 18
+ BaseCommand_PONG BaseCommand_Type = 19
+ BaseCommand_REDELIVER_UNACKNOWLEDGED_MESSAGES BaseCommand_Type = 20
+ BaseCommand_PARTITIONED_METADATA BaseCommand_Type = 21
+ BaseCommand_PARTITIONED_METADATA_RESPONSE BaseCommand_Type = 22
+ BaseCommand_LOOKUP BaseCommand_Type = 23
+ BaseCommand_LOOKUP_RESPONSE BaseCommand_Type = 24
+ BaseCommand_CONSUMER_STATS BaseCommand_Type = 25
+ BaseCommand_CONSUMER_STATS_RESPONSE BaseCommand_Type = 26
+ BaseCommand_REACHED_END_OF_TOPIC BaseCommand_Type = 27
+ BaseCommand_SEEK BaseCommand_Type = 28
+ BaseCommand_GET_LAST_MESSAGE_ID BaseCommand_Type = 29
+ BaseCommand_GET_LAST_MESSAGE_ID_RESPONSE BaseCommand_Type = 30
+ BaseCommand_ACTIVE_CONSUMER_CHANGE BaseCommand_Type = 31
+ BaseCommand_GET_TOPICS_OF_NAMESPACE BaseCommand_Type = 32
+ BaseCommand_GET_TOPICS_OF_NAMESPACE_RESPONSE BaseCommand_Type = 33
+ BaseCommand_GET_SCHEMA BaseCommand_Type = 34
+ BaseCommand_GET_SCHEMA_RESPONSE BaseCommand_Type = 35
+ BaseCommand_AUTH_CHALLENGE BaseCommand_Type = 36
+ BaseCommand_AUTH_RESPONSE BaseCommand_Type = 37
+ BaseCommand_ACK_RESPONSE BaseCommand_Type = 38
+ BaseCommand_GET_OR_CREATE_SCHEMA BaseCommand_Type = 39
+ BaseCommand_GET_OR_CREATE_SCHEMA_RESPONSE BaseCommand_Type = 40
+ // transaction related
+ BaseCommand_NEW_TXN BaseCommand_Type = 50
+ BaseCommand_NEW_TXN_RESPONSE BaseCommand_Type = 51
+ BaseCommand_ADD_PARTITION_TO_TXN BaseCommand_Type = 52
+ BaseCommand_ADD_PARTITION_TO_TXN_RESPONSE BaseCommand_Type = 53
+ BaseCommand_ADD_SUBSCRIPTION_TO_TXN BaseCommand_Type = 54
+ BaseCommand_ADD_SUBSCRIPTION_TO_TXN_RESPONSE BaseCommand_Type = 55
+ BaseCommand_END_TXN BaseCommand_Type = 56
+ BaseCommand_END_TXN_RESPONSE BaseCommand_Type = 57
+ BaseCommand_END_TXN_ON_PARTITION BaseCommand_Type = 58
+ BaseCommand_END_TXN_ON_PARTITION_RESPONSE BaseCommand_Type = 59
+ BaseCommand_END_TXN_ON_SUBSCRIPTION BaseCommand_Type = 60
+ BaseCommand_END_TXN_ON_SUBSCRIPTION_RESPONSE BaseCommand_Type = 61
+ BaseCommand_TC_CLIENT_CONNECT_REQUEST BaseCommand_Type = 62
+ BaseCommand_TC_CLIENT_CONNECT_RESPONSE BaseCommand_Type = 63
+ BaseCommand_WATCH_TOPIC_LIST BaseCommand_Type = 64
+ BaseCommand_WATCH_TOPIC_LIST_SUCCESS BaseCommand_Type = 65
+ BaseCommand_WATCH_TOPIC_UPDATE BaseCommand_Type = 66
+ BaseCommand_WATCH_TOPIC_LIST_CLOSE BaseCommand_Type = 67
+)
+
+// Enum value maps for BaseCommand_Type.
+var (
+ BaseCommand_Type_name = map[int32]string{
+ 2: "CONNECT",
+ 3: "CONNECTED",
+ 4: "SUBSCRIBE",
+ 5: "PRODUCER",
+ 6: "SEND",
+ 7: "SEND_RECEIPT",
+ 8: "SEND_ERROR",
+ 9: "MESSAGE",
+ 10: "ACK",
+ 11: "FLOW",
+ 12: "UNSUBSCRIBE",
+ 13: "SUCCESS",
+ 14: "ERROR",
+ 15: "CLOSE_PRODUCER",
+ 16: "CLOSE_CONSUMER",
+ 17: "PRODUCER_SUCCESS",
+ 18: "PING",
+ 19: "PONG",
+ 20: "REDELIVER_UNACKNOWLEDGED_MESSAGES",
+ 21: "PARTITIONED_METADATA",
+ 22: "PARTITIONED_METADATA_RESPONSE",
+ 23: "LOOKUP",
+ 24: "LOOKUP_RESPONSE",
+ 25: "CONSUMER_STATS",
+ 26: "CONSUMER_STATS_RESPONSE",
+ 27: "REACHED_END_OF_TOPIC",
+ 28: "SEEK",
+ 29: "GET_LAST_MESSAGE_ID",
+ 30: "GET_LAST_MESSAGE_ID_RESPONSE",
+ 31: "ACTIVE_CONSUMER_CHANGE",
+ 32: "GET_TOPICS_OF_NAMESPACE",
+ 33: "GET_TOPICS_OF_NAMESPACE_RESPONSE",
+ 34: "GET_SCHEMA",
+ 35: "GET_SCHEMA_RESPONSE",
+ 36: "AUTH_CHALLENGE",
+ 37: "AUTH_RESPONSE",
+ 38: "ACK_RESPONSE",
+ 39: "GET_OR_CREATE_SCHEMA",
+ 40: "GET_OR_CREATE_SCHEMA_RESPONSE",
+ 50: "NEW_TXN",
+ 51: "NEW_TXN_RESPONSE",
+ 52: "ADD_PARTITION_TO_TXN",
+ 53: "ADD_PARTITION_TO_TXN_RESPONSE",
+ 54: "ADD_SUBSCRIPTION_TO_TXN",
+ 55: "ADD_SUBSCRIPTION_TO_TXN_RESPONSE",
+ 56: "END_TXN",
+ 57: "END_TXN_RESPONSE",
+ 58: "END_TXN_ON_PARTITION",
+ 59: "END_TXN_ON_PARTITION_RESPONSE",
+ 60: "END_TXN_ON_SUBSCRIPTION",
+ 61: "END_TXN_ON_SUBSCRIPTION_RESPONSE",
+ 62: "TC_CLIENT_CONNECT_REQUEST",
+ 63: "TC_CLIENT_CONNECT_RESPONSE",
+ 64: "WATCH_TOPIC_LIST",
+ 65: "WATCH_TOPIC_LIST_SUCCESS",
+ 66: "WATCH_TOPIC_UPDATE",
+ 67: "WATCH_TOPIC_LIST_CLOSE",
+ }
+ BaseCommand_Type_value = map[string]int32{
+ "CONNECT": 2,
+ "CONNECTED": 3,
+ "SUBSCRIBE": 4,
+ "PRODUCER": 5,
+ "SEND": 6,
+ "SEND_RECEIPT": 7,
+ "SEND_ERROR": 8,
+ "MESSAGE": 9,
+ "ACK": 10,
+ "FLOW": 11,
+ "UNSUBSCRIBE": 12,
+ "SUCCESS": 13,
+ "ERROR": 14,
+ "CLOSE_PRODUCER": 15,
+ "CLOSE_CONSUMER": 16,
+ "PRODUCER_SUCCESS": 17,
+ "PING": 18,
+ "PONG": 19,
+ "REDELIVER_UNACKNOWLEDGED_MESSAGES": 20,
+ "PARTITIONED_METADATA": 21,
+ "PARTITIONED_METADATA_RESPONSE": 22,
+ "LOOKUP": 23,
+ "LOOKUP_RESPONSE": 24,
+ "CONSUMER_STATS": 25,
+ "CONSUMER_STATS_RESPONSE": 26,
+ "REACHED_END_OF_TOPIC": 27,
+ "SEEK": 28,
+ "GET_LAST_MESSAGE_ID": 29,
+ "GET_LAST_MESSAGE_ID_RESPONSE": 30,
+ "ACTIVE_CONSUMER_CHANGE": 31,
+ "GET_TOPICS_OF_NAMESPACE": 32,
+ "GET_TOPICS_OF_NAMESPACE_RESPONSE": 33,
+ "GET_SCHEMA": 34,
+ "GET_SCHEMA_RESPONSE": 35,
+ "AUTH_CHALLENGE": 36,
+ "AUTH_RESPONSE": 37,
+ "ACK_RESPONSE": 38,
+ "GET_OR_CREATE_SCHEMA": 39,
+ "GET_OR_CREATE_SCHEMA_RESPONSE": 40,
+ "NEW_TXN": 50,
+ "NEW_TXN_RESPONSE": 51,
+ "ADD_PARTITION_TO_TXN": 52,
+ "ADD_PARTITION_TO_TXN_RESPONSE": 53,
+ "ADD_SUBSCRIPTION_TO_TXN": 54,
+ "ADD_SUBSCRIPTION_TO_TXN_RESPONSE": 55,
+ "END_TXN": 56,
+ "END_TXN_RESPONSE": 57,
+ "END_TXN_ON_PARTITION": 58,
+ "END_TXN_ON_PARTITION_RESPONSE": 59,
+ "END_TXN_ON_SUBSCRIPTION": 60,
+ "END_TXN_ON_SUBSCRIPTION_RESPONSE": 61,
+ "TC_CLIENT_CONNECT_REQUEST": 62,
+ "TC_CLIENT_CONNECT_RESPONSE": 63,
+ "WATCH_TOPIC_LIST": 64,
+ "WATCH_TOPIC_LIST_SUCCESS": 65,
+ "WATCH_TOPIC_UPDATE": 66,
+ "WATCH_TOPIC_LIST_CLOSE": 67,
+ }
+)
+
+func (x BaseCommand_Type) Enum() *BaseCommand_Type {
+ p := new(BaseCommand_Type)
+ *p = x
+ return p
+}
+
+func (x BaseCommand_Type) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (BaseCommand_Type) Descriptor() protoreflect.EnumDescriptor {
+ return file_PulsarApi_proto_enumTypes[15].Descriptor()
+}
+
+func (BaseCommand_Type) Type() protoreflect.EnumType {
+ return &file_PulsarApi_proto_enumTypes[15]
+}
+
+func (x BaseCommand_Type) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *BaseCommand_Type) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = BaseCommand_Type(num)
+ return nil
+}
+
+// Deprecated: Use BaseCommand_Type.Descriptor instead.
+func (BaseCommand_Type) EnumDescriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{70, 0}
+}
+
+type Schema struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
+ SchemaData []byte `protobuf:"bytes,3,req,name=schema_data,json=schemaData" json:"schema_data,omitempty"`
+ Type *Schema_Type `protobuf:"varint,4,req,name=type,enum=pulsar.proto.Schema_Type" json:"type,omitempty"`
+ Properties []*KeyValue `protobuf:"bytes,5,rep,name=properties" json:"properties,omitempty"`
+}
+
+func (x *Schema) Reset() {
+ *x = Schema{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Schema) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Schema) ProtoMessage() {}
+
+func (x *Schema) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Schema.ProtoReflect.Descriptor instead.
+func (*Schema) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Schema) GetName() string {
+ if x != nil && x.Name != nil {
+ return *x.Name
+ }
+ return ""
+}
+
+func (x *Schema) GetSchemaData() []byte {
+ if x != nil {
+ return x.SchemaData
+ }
+ return nil
+}
+
+func (x *Schema) GetType() Schema_Type {
+ if x != nil && x.Type != nil {
+ return *x.Type
+ }
+ return Schema_None
+}
+
+func (x *Schema) GetProperties() []*KeyValue {
+ if x != nil {
+ return x.Properties
+ }
+ return nil
+}
+
+type MessageIdData struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ LedgerId *uint64 `protobuf:"varint,1,req,name=ledgerId" json:"ledgerId,omitempty"`
+ EntryId *uint64 `protobuf:"varint,2,req,name=entryId" json:"entryId,omitempty"`
+ Partition *int32 `protobuf:"varint,3,opt,name=partition,def=-1" json:"partition,omitempty"`
+ BatchIndex *int32 `protobuf:"varint,4,opt,name=batch_index,json=batchIndex,def=-1" json:"batch_index,omitempty"`
+ AckSet []int64 `protobuf:"varint,5,rep,name=ack_set,json=ackSet" json:"ack_set,omitempty"`
+ BatchSize *int32 `protobuf:"varint,6,opt,name=batch_size,json=batchSize" json:"batch_size,omitempty"`
+ // For the chunk message id, we need to specify the first chunk message id.
+ FirstChunkMessageId *MessageIdData `protobuf:"bytes,7,opt,name=first_chunk_message_id,json=firstChunkMessageId" json:"first_chunk_message_id,omitempty"`
+}
+
+// Default values for MessageIdData fields.
+const (
+ Default_MessageIdData_Partition = int32(-1)
+ Default_MessageIdData_BatchIndex = int32(-1)
+)
+
+func (x *MessageIdData) Reset() {
+ *x = MessageIdData{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *MessageIdData) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MessageIdData) ProtoMessage() {}
+
+func (x *MessageIdData) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use MessageIdData.ProtoReflect.Descriptor instead.
+func (*MessageIdData) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *MessageIdData) GetLedgerId() uint64 {
+ if x != nil && x.LedgerId != nil {
+ return *x.LedgerId
+ }
+ return 0
+}
+
+func (x *MessageIdData) GetEntryId() uint64 {
+ if x != nil && x.EntryId != nil {
+ return *x.EntryId
+ }
+ return 0
+}
+
+func (x *MessageIdData) GetPartition() int32 {
+ if x != nil && x.Partition != nil {
+ return *x.Partition
+ }
+ return Default_MessageIdData_Partition
+}
+
+func (x *MessageIdData) GetBatchIndex() int32 {
+ if x != nil && x.BatchIndex != nil {
+ return *x.BatchIndex
+ }
+ return Default_MessageIdData_BatchIndex
+}
+
+func (x *MessageIdData) GetAckSet() []int64 {
+ if x != nil {
+ return x.AckSet
+ }
+ return nil
+}
+
+func (x *MessageIdData) GetBatchSize() int32 {
+ if x != nil && x.BatchSize != nil {
+ return *x.BatchSize
+ }
+ return 0
+}
+
+func (x *MessageIdData) GetFirstChunkMessageId() *MessageIdData {
+ if x != nil {
+ return x.FirstChunkMessageId
+ }
+ return nil
+}
+
+type KeyValue struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Key *string `protobuf:"bytes,1,req,name=key" json:"key,omitempty"`
+ Value *string `protobuf:"bytes,2,req,name=value" json:"value,omitempty"`
+}
+
+func (x *KeyValue) Reset() {
+ *x = KeyValue{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *KeyValue) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*KeyValue) ProtoMessage() {}
+
+func (x *KeyValue) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use KeyValue.ProtoReflect.Descriptor instead.
+func (*KeyValue) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *KeyValue) GetKey() string {
+ if x != nil && x.Key != nil {
+ return *x.Key
+ }
+ return ""
+}
+
+func (x *KeyValue) GetValue() string {
+ if x != nil && x.Value != nil {
+ return *x.Value
+ }
+ return ""
+}
+
+type KeyLongValue struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Key *string `protobuf:"bytes,1,req,name=key" json:"key,omitempty"`
+ Value *uint64 `protobuf:"varint,2,req,name=value" json:"value,omitempty"`
+}
+
+func (x *KeyLongValue) Reset() {
+ *x = KeyLongValue{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *KeyLongValue) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*KeyLongValue) ProtoMessage() {}
+
+func (x *KeyLongValue) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use KeyLongValue.ProtoReflect.Descriptor instead.
+func (*KeyLongValue) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *KeyLongValue) GetKey() string {
+ if x != nil && x.Key != nil {
+ return *x.Key
+ }
+ return ""
+}
+
+func (x *KeyLongValue) GetValue() uint64 {
+ if x != nil && x.Value != nil {
+ return *x.Value
+ }
+ return 0
+}
+
+type IntRange struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Start *int32 `protobuf:"varint,1,req,name=start" json:"start,omitempty"`
+ End *int32 `protobuf:"varint,2,req,name=end" json:"end,omitempty"`
+}
+
+func (x *IntRange) Reset() {
+ *x = IntRange{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *IntRange) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*IntRange) ProtoMessage() {}
+
+func (x *IntRange) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use IntRange.ProtoReflect.Descriptor instead.
+func (*IntRange) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *IntRange) GetStart() int32 {
+ if x != nil && x.Start != nil {
+ return *x.Start
+ }
+ return 0
+}
+
+func (x *IntRange) GetEnd() int32 {
+ if x != nil && x.End != nil {
+ return *x.End
+ }
+ return 0
+}
+
+type EncryptionKeys struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Key *string `protobuf:"bytes,1,req,name=key" json:"key,omitempty"`
+ Value []byte `protobuf:"bytes,2,req,name=value" json:"value,omitempty"`
+ Metadata []*KeyValue `protobuf:"bytes,3,rep,name=metadata" json:"metadata,omitempty"`
+}
+
+func (x *EncryptionKeys) Reset() {
+ *x = EncryptionKeys{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EncryptionKeys) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EncryptionKeys) ProtoMessage() {}
+
+func (x *EncryptionKeys) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EncryptionKeys.ProtoReflect.Descriptor instead.
+func (*EncryptionKeys) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *EncryptionKeys) GetKey() string {
+ if x != nil && x.Key != nil {
+ return *x.Key
+ }
+ return ""
+}
+
+func (x *EncryptionKeys) GetValue() []byte {
+ if x != nil {
+ return x.Value
+ }
+ return nil
+}
+
+func (x *EncryptionKeys) GetMetadata() []*KeyValue {
+ if x != nil {
+ return x.Metadata
+ }
+ return nil
+}
+
+type MessageMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ProducerName *string `protobuf:"bytes,1,req,name=producer_name,json=producerName" json:"producer_name,omitempty"`
+ SequenceId *uint64 `protobuf:"varint,2,req,name=sequence_id,json=sequenceId" json:"sequence_id,omitempty"`
+ PublishTime *uint64 `protobuf:"varint,3,req,name=publish_time,json=publishTime" json:"publish_time,omitempty"`
+ Properties []*KeyValue `protobuf:"bytes,4,rep,name=properties" json:"properties,omitempty"`
+ // Property set on replicated message,
+ // includes the source cluster name
+ ReplicatedFrom *string `protobuf:"bytes,5,opt,name=replicated_from,json=replicatedFrom" json:"replicated_from,omitempty"`
+ //key to decide partition for the msg
+ PartitionKey *string `protobuf:"bytes,6,opt,name=partition_key,json=partitionKey" json:"partition_key,omitempty"`
+ // Override namespace's replication
+ ReplicateTo []string `protobuf:"bytes,7,rep,name=replicate_to,json=replicateTo" json:"replicate_to,omitempty"`
+ Compression *CompressionType `protobuf:"varint,8,opt,name=compression,enum=pulsar.proto.CompressionType,def=0" json:"compression,omitempty"`
+ UncompressedSize *uint32 `protobuf:"varint,9,opt,name=uncompressed_size,json=uncompressedSize,def=0" json:"uncompressed_size,omitempty"`
+ // Removed below checksum field from Metadata as
+ // it should be part of send-command which keeps checksum of header + payload
+ //optional sfixed64 checksum = 10;
+ // differentiate single and batch message metadata
+ NumMessagesInBatch *int32 `protobuf:"varint,11,opt,name=num_messages_in_batch,json=numMessagesInBatch,def=1" json:"num_messages_in_batch,omitempty"`
+ // the timestamp that this event occurs. it is typically set by applications.
+ // if this field is omitted, `publish_time` can be used for the purpose of `event_time`.
+ EventTime *uint64 `protobuf:"varint,12,opt,name=event_time,json=eventTime,def=0" json:"event_time,omitempty"`
+ // Contains encryption key name, encrypted key and metadata to describe the key
+ EncryptionKeys []*EncryptionKeys `protobuf:"bytes,13,rep,name=encryption_keys,json=encryptionKeys" json:"encryption_keys,omitempty"`
+ // Algorithm used to encrypt data key
+ EncryptionAlgo *string `protobuf:"bytes,14,opt,name=encryption_algo,json=encryptionAlgo" json:"encryption_algo,omitempty"`
+ // Additional parameters required by encryption
+ EncryptionParam []byte `protobuf:"bytes,15,opt,name=encryption_param,json=encryptionParam" json:"encryption_param,omitempty"`
+ SchemaVersion []byte `protobuf:"bytes,16,opt,name=schema_version,json=schemaVersion" json:"schema_version,omitempty"`
+ PartitionKeyB64Encoded *bool `protobuf:"varint,17,opt,name=partition_key_b64_encoded,json=partitionKeyB64Encoded,def=0" json:"partition_key_b64_encoded,omitempty"`
+ // Specific a key to overwrite the message key which used for ordering dispatch in Key_Shared mode.
+ OrderingKey []byte `protobuf:"bytes,18,opt,name=ordering_key,json=orderingKey" json:"ordering_key,omitempty"`
+ // Mark the message to be delivered at or after the specified timestamp
+ DeliverAtTime *int64 `protobuf:"varint,19,opt,name=deliver_at_time,json=deliverAtTime" json:"deliver_at_time,omitempty"`
+ // Identify whether a message is a "marker" message used for
+ // internal metadata instead of application published data.
+ // Markers will generally not be propagated back to clients
+ MarkerType *int32 `protobuf:"varint,20,opt,name=marker_type,json=markerType" json:"marker_type,omitempty"`
+ // transaction related message info
+ TxnidLeastBits *uint64 `protobuf:"varint,22,opt,name=txnid_least_bits,json=txnidLeastBits" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,23,opt,name=txnid_most_bits,json=txnidMostBits" json:"txnid_most_bits,omitempty"`
+ /// Add highest sequence id to support batch message with external sequence id
+ HighestSequenceId *uint64 `protobuf:"varint,24,opt,name=highest_sequence_id,json=highestSequenceId,def=0" json:"highest_sequence_id,omitempty"`
+ // Indicate if the message payload value is set
+ NullValue *bool `protobuf:"varint,25,opt,name=null_value,json=nullValue,def=0" json:"null_value,omitempty"`
+ Uuid *string `protobuf:"bytes,26,opt,name=uuid" json:"uuid,omitempty"`
+ NumChunksFromMsg *int32 `protobuf:"varint,27,opt,name=num_chunks_from_msg,json=numChunksFromMsg" json:"num_chunks_from_msg,omitempty"`
+ TotalChunkMsgSize *int32 `protobuf:"varint,28,opt,name=total_chunk_msg_size,json=totalChunkMsgSize" json:"total_chunk_msg_size,omitempty"`
+ ChunkId *int32 `protobuf:"varint,29,opt,name=chunk_id,json=chunkId" json:"chunk_id,omitempty"`
+ // Indicate if the message partition key is set
+ NullPartitionKey *bool `protobuf:"varint,30,opt,name=null_partition_key,json=nullPartitionKey,def=0" json:"null_partition_key,omitempty"`
+}
+
+// Default values for MessageMetadata fields.
+const (
+ Default_MessageMetadata_Compression = CompressionType_NONE
+ Default_MessageMetadata_UncompressedSize = uint32(0)
+ Default_MessageMetadata_NumMessagesInBatch = int32(1)
+ Default_MessageMetadata_EventTime = uint64(0)
+ Default_MessageMetadata_PartitionKeyB64Encoded = bool(false)
+ Default_MessageMetadata_HighestSequenceId = uint64(0)
+ Default_MessageMetadata_NullValue = bool(false)
+ Default_MessageMetadata_NullPartitionKey = bool(false)
+)
+
+func (x *MessageMetadata) Reset() {
+ *x = MessageMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *MessageMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MessageMetadata) ProtoMessage() {}
+
+func (x *MessageMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use MessageMetadata.ProtoReflect.Descriptor instead.
+func (*MessageMetadata) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *MessageMetadata) GetProducerName() string {
+ if x != nil && x.ProducerName != nil {
+ return *x.ProducerName
+ }
+ return ""
+}
+
+func (x *MessageMetadata) GetSequenceId() uint64 {
+ if x != nil && x.SequenceId != nil {
+ return *x.SequenceId
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetPublishTime() uint64 {
+ if x != nil && x.PublishTime != nil {
+ return *x.PublishTime
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetProperties() []*KeyValue {
+ if x != nil {
+ return x.Properties
+ }
+ return nil
+}
+
+func (x *MessageMetadata) GetReplicatedFrom() string {
+ if x != nil && x.ReplicatedFrom != nil {
+ return *x.ReplicatedFrom
+ }
+ return ""
+}
+
+func (x *MessageMetadata) GetPartitionKey() string {
+ if x != nil && x.PartitionKey != nil {
+ return *x.PartitionKey
+ }
+ return ""
+}
+
+func (x *MessageMetadata) GetReplicateTo() []string {
+ if x != nil {
+ return x.ReplicateTo
+ }
+ return nil
+}
+
+func (x *MessageMetadata) GetCompression() CompressionType {
+ if x != nil && x.Compression != nil {
+ return *x.Compression
+ }
+ return Default_MessageMetadata_Compression
+}
+
+func (x *MessageMetadata) GetUncompressedSize() uint32 {
+ if x != nil && x.UncompressedSize != nil {
+ return *x.UncompressedSize
+ }
+ return Default_MessageMetadata_UncompressedSize
+}
+
+func (x *MessageMetadata) GetNumMessagesInBatch() int32 {
+ if x != nil && x.NumMessagesInBatch != nil {
+ return *x.NumMessagesInBatch
+ }
+ return Default_MessageMetadata_NumMessagesInBatch
+}
+
+func (x *MessageMetadata) GetEventTime() uint64 {
+ if x != nil && x.EventTime != nil {
+ return *x.EventTime
+ }
+ return Default_MessageMetadata_EventTime
+}
+
+func (x *MessageMetadata) GetEncryptionKeys() []*EncryptionKeys {
+ if x != nil {
+ return x.EncryptionKeys
+ }
+ return nil
+}
+
+func (x *MessageMetadata) GetEncryptionAlgo() string {
+ if x != nil && x.EncryptionAlgo != nil {
+ return *x.EncryptionAlgo
+ }
+ return ""
+}
+
+func (x *MessageMetadata) GetEncryptionParam() []byte {
+ if x != nil {
+ return x.EncryptionParam
+ }
+ return nil
+}
+
+func (x *MessageMetadata) GetSchemaVersion() []byte {
+ if x != nil {
+ return x.SchemaVersion
+ }
+ return nil
+}
+
+func (x *MessageMetadata) GetPartitionKeyB64Encoded() bool {
+ if x != nil && x.PartitionKeyB64Encoded != nil {
+ return *x.PartitionKeyB64Encoded
+ }
+ return Default_MessageMetadata_PartitionKeyB64Encoded
+}
+
+func (x *MessageMetadata) GetOrderingKey() []byte {
+ if x != nil {
+ return x.OrderingKey
+ }
+ return nil
+}
+
+func (x *MessageMetadata) GetDeliverAtTime() int64 {
+ if x != nil && x.DeliverAtTime != nil {
+ return *x.DeliverAtTime
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetMarkerType() int32 {
+ if x != nil && x.MarkerType != nil {
+ return *x.MarkerType
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetHighestSequenceId() uint64 {
+ if x != nil && x.HighestSequenceId != nil {
+ return *x.HighestSequenceId
+ }
+ return Default_MessageMetadata_HighestSequenceId
+}
+
+func (x *MessageMetadata) GetNullValue() bool {
+ if x != nil && x.NullValue != nil {
+ return *x.NullValue
+ }
+ return Default_MessageMetadata_NullValue
+}
+
+func (x *MessageMetadata) GetUuid() string {
+ if x != nil && x.Uuid != nil {
+ return *x.Uuid
+ }
+ return ""
+}
+
+func (x *MessageMetadata) GetNumChunksFromMsg() int32 {
+ if x != nil && x.NumChunksFromMsg != nil {
+ return *x.NumChunksFromMsg
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetTotalChunkMsgSize() int32 {
+ if x != nil && x.TotalChunkMsgSize != nil {
+ return *x.TotalChunkMsgSize
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetChunkId() int32 {
+ if x != nil && x.ChunkId != nil {
+ return *x.ChunkId
+ }
+ return 0
+}
+
+func (x *MessageMetadata) GetNullPartitionKey() bool {
+ if x != nil && x.NullPartitionKey != nil {
+ return *x.NullPartitionKey
+ }
+ return Default_MessageMetadata_NullPartitionKey
+}
+
+type SingleMessageMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Properties []*KeyValue `protobuf:"bytes,1,rep,name=properties" json:"properties,omitempty"`
+ PartitionKey *string `protobuf:"bytes,2,opt,name=partition_key,json=partitionKey" json:"partition_key,omitempty"`
+ PayloadSize *int32 `protobuf:"varint,3,req,name=payload_size,json=payloadSize" json:"payload_size,omitempty"`
+ CompactedOut *bool `protobuf:"varint,4,opt,name=compacted_out,json=compactedOut,def=0" json:"compacted_out,omitempty"`
+ // the timestamp that this event occurs. it is typically set by applications.
+ // if this field is omitted, `publish_time` can be used for the purpose of `event_time`.
+ EventTime *uint64 `protobuf:"varint,5,opt,name=event_time,json=eventTime,def=0" json:"event_time,omitempty"`
+ PartitionKeyB64Encoded *bool `protobuf:"varint,6,opt,name=partition_key_b64_encoded,json=partitionKeyB64Encoded,def=0" json:"partition_key_b64_encoded,omitempty"`
+ // Specific a key to overwrite the message key which used for ordering dispatch in Key_Shared mode.
+ OrderingKey []byte `protobuf:"bytes,7,opt,name=ordering_key,json=orderingKey" json:"ordering_key,omitempty"`
+ // Allows consumer retrieve the sequence id that the producer set.
+ SequenceId *uint64 `protobuf:"varint,8,opt,name=sequence_id,json=sequenceId" json:"sequence_id,omitempty"`
+ // Indicate if the message payload value is set
+ NullValue *bool `protobuf:"varint,9,opt,name=null_value,json=nullValue,def=0" json:"null_value,omitempty"`
+ // Indicate if the message partition key is set
+ NullPartitionKey *bool `protobuf:"varint,10,opt,name=null_partition_key,json=nullPartitionKey,def=0" json:"null_partition_key,omitempty"`
+}
+
+// Default values for SingleMessageMetadata fields.
+const (
+ Default_SingleMessageMetadata_CompactedOut = bool(false)
+ Default_SingleMessageMetadata_EventTime = uint64(0)
+ Default_SingleMessageMetadata_PartitionKeyB64Encoded = bool(false)
+ Default_SingleMessageMetadata_NullValue = bool(false)
+ Default_SingleMessageMetadata_NullPartitionKey = bool(false)
+)
+
+func (x *SingleMessageMetadata) Reset() {
+ *x = SingleMessageMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SingleMessageMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SingleMessageMetadata) ProtoMessage() {}
+
+func (x *SingleMessageMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SingleMessageMetadata.ProtoReflect.Descriptor instead.
+func (*SingleMessageMetadata) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *SingleMessageMetadata) GetProperties() []*KeyValue {
+ if x != nil {
+ return x.Properties
+ }
+ return nil
+}
+
+func (x *SingleMessageMetadata) GetPartitionKey() string {
+ if x != nil && x.PartitionKey != nil {
+ return *x.PartitionKey
+ }
+ return ""
+}
+
+func (x *SingleMessageMetadata) GetPayloadSize() int32 {
+ if x != nil && x.PayloadSize != nil {
+ return *x.PayloadSize
+ }
+ return 0
+}
+
+func (x *SingleMessageMetadata) GetCompactedOut() bool {
+ if x != nil && x.CompactedOut != nil {
+ return *x.CompactedOut
+ }
+ return Default_SingleMessageMetadata_CompactedOut
+}
+
+func (x *SingleMessageMetadata) GetEventTime() uint64 {
+ if x != nil && x.EventTime != nil {
+ return *x.EventTime
+ }
+ return Default_SingleMessageMetadata_EventTime
+}
+
+func (x *SingleMessageMetadata) GetPartitionKeyB64Encoded() bool {
+ if x != nil && x.PartitionKeyB64Encoded != nil {
+ return *x.PartitionKeyB64Encoded
+ }
+ return Default_SingleMessageMetadata_PartitionKeyB64Encoded
+}
+
+func (x *SingleMessageMetadata) GetOrderingKey() []byte {
+ if x != nil {
+ return x.OrderingKey
+ }
+ return nil
+}
+
+func (x *SingleMessageMetadata) GetSequenceId() uint64 {
+ if x != nil && x.SequenceId != nil {
+ return *x.SequenceId
+ }
+ return 0
+}
+
+func (x *SingleMessageMetadata) GetNullValue() bool {
+ if x != nil && x.NullValue != nil {
+ return *x.NullValue
+ }
+ return Default_SingleMessageMetadata_NullValue
+}
+
+func (x *SingleMessageMetadata) GetNullPartitionKey() bool {
+ if x != nil && x.NullPartitionKey != nil {
+ return *x.NullPartitionKey
+ }
+ return Default_SingleMessageMetadata_NullPartitionKey
+}
+
+// metadata added for entry from broker
+type BrokerEntryMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ BrokerTimestamp *uint64 `protobuf:"varint,1,opt,name=broker_timestamp,json=brokerTimestamp" json:"broker_timestamp,omitempty"`
+ Index *uint64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"`
+}
+
+func (x *BrokerEntryMetadata) Reset() {
+ *x = BrokerEntryMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BrokerEntryMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BrokerEntryMetadata) ProtoMessage() {}
+
+func (x *BrokerEntryMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BrokerEntryMetadata.ProtoReflect.Descriptor instead.
+func (*BrokerEntryMetadata) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *BrokerEntryMetadata) GetBrokerTimestamp() uint64 {
+ if x != nil && x.BrokerTimestamp != nil {
+ return *x.BrokerTimestamp
+ }
+ return 0
+}
+
+func (x *BrokerEntryMetadata) GetIndex() uint64 {
+ if x != nil && x.Index != nil {
+ return *x.Index
+ }
+ return 0
+}
+
+type CommandConnect struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClientVersion *string `protobuf:"bytes,1,req,name=client_version,json=clientVersion" json:"client_version,omitempty"`
+ AuthMethod *AuthMethod `protobuf:"varint,2,opt,name=auth_method,json=authMethod,enum=pulsar.proto.AuthMethod" json:"auth_method,omitempty"` // Deprecated. Use "auth_method_name" instead.
+ AuthMethodName *string `protobuf:"bytes,5,opt,name=auth_method_name,json=authMethodName" json:"auth_method_name,omitempty"`
+ AuthData []byte `protobuf:"bytes,3,opt,name=auth_data,json=authData" json:"auth_data,omitempty"`
+ ProtocolVersion *int32 `protobuf:"varint,4,opt,name=protocol_version,json=protocolVersion,def=0" json:"protocol_version,omitempty"`
+ // Client can ask to be proxyied to a specific broker
+ // This is only honored by a Pulsar proxy
+ ProxyToBrokerUrl *string `protobuf:"bytes,6,opt,name=proxy_to_broker_url,json=proxyToBrokerUrl" json:"proxy_to_broker_url,omitempty"`
+ // Original principal that was verified by
+ // a Pulsar proxy. In this case the auth info above
+ // will be the auth of the proxy itself
+ OriginalPrincipal *string `protobuf:"bytes,7,opt,name=original_principal,json=originalPrincipal" json:"original_principal,omitempty"`
+ // Original auth role and auth Method that was passed
+ // to the proxy. In this case the auth info above
+ // will be the auth of the proxy itself
+ OriginalAuthData *string `protobuf:"bytes,8,opt,name=original_auth_data,json=originalAuthData" json:"original_auth_data,omitempty"`
+ OriginalAuthMethod *string `protobuf:"bytes,9,opt,name=original_auth_method,json=originalAuthMethod" json:"original_auth_method,omitempty"`
+ // Feature flags
+ FeatureFlags *FeatureFlags `protobuf:"bytes,10,opt,name=feature_flags,json=featureFlags" json:"feature_flags,omitempty"`
+}
+
+// Default values for CommandConnect fields.
+const (
+ Default_CommandConnect_ProtocolVersion = int32(0)
+)
+
+func (x *CommandConnect) Reset() {
+ *x = CommandConnect{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandConnect) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandConnect) ProtoMessage() {}
+
+func (x *CommandConnect) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandConnect.ProtoReflect.Descriptor instead.
+func (*CommandConnect) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *CommandConnect) GetClientVersion() string {
+ if x != nil && x.ClientVersion != nil {
+ return *x.ClientVersion
+ }
+ return ""
+}
+
+func (x *CommandConnect) GetAuthMethod() AuthMethod {
+ if x != nil && x.AuthMethod != nil {
+ return *x.AuthMethod
+ }
+ return AuthMethod_AuthMethodNone
+}
+
+func (x *CommandConnect) GetAuthMethodName() string {
+ if x != nil && x.AuthMethodName != nil {
+ return *x.AuthMethodName
+ }
+ return ""
+}
+
+func (x *CommandConnect) GetAuthData() []byte {
+ if x != nil {
+ return x.AuthData
+ }
+ return nil
+}
+
+func (x *CommandConnect) GetProtocolVersion() int32 {
+ if x != nil && x.ProtocolVersion != nil {
+ return *x.ProtocolVersion
+ }
+ return Default_CommandConnect_ProtocolVersion
+}
+
+func (x *CommandConnect) GetProxyToBrokerUrl() string {
+ if x != nil && x.ProxyToBrokerUrl != nil {
+ return *x.ProxyToBrokerUrl
+ }
+ return ""
+}
+
+func (x *CommandConnect) GetOriginalPrincipal() string {
+ if x != nil && x.OriginalPrincipal != nil {
+ return *x.OriginalPrincipal
+ }
+ return ""
+}
+
+func (x *CommandConnect) GetOriginalAuthData() string {
+ if x != nil && x.OriginalAuthData != nil {
+ return *x.OriginalAuthData
+ }
+ return ""
+}
+
+func (x *CommandConnect) GetOriginalAuthMethod() string {
+ if x != nil && x.OriginalAuthMethod != nil {
+ return *x.OriginalAuthMethod
+ }
+ return ""
+}
+
+func (x *CommandConnect) GetFeatureFlags() *FeatureFlags {
+ if x != nil {
+ return x.FeatureFlags
+ }
+ return nil
+}
+
+type FeatureFlags struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ SupportsAuthRefresh *bool `protobuf:"varint,1,opt,name=supports_auth_refresh,json=supportsAuthRefresh,def=0" json:"supports_auth_refresh,omitempty"`
+ SupportsBrokerEntryMetadata *bool `protobuf:"varint,2,opt,name=supports_broker_entry_metadata,json=supportsBrokerEntryMetadata,def=0" json:"supports_broker_entry_metadata,omitempty"`
+ SupportsPartialProducer *bool `protobuf:"varint,3,opt,name=supports_partial_producer,json=supportsPartialProducer,def=0" json:"supports_partial_producer,omitempty"`
+ SupportsTopicWatchers *bool `protobuf:"varint,4,opt,name=supports_topic_watchers,json=supportsTopicWatchers,def=0" json:"supports_topic_watchers,omitempty"`
+}
+
+// Default values for FeatureFlags fields.
+const (
+ Default_FeatureFlags_SupportsAuthRefresh = bool(false)
+ Default_FeatureFlags_SupportsBrokerEntryMetadata = bool(false)
+ Default_FeatureFlags_SupportsPartialProducer = bool(false)
+ Default_FeatureFlags_SupportsTopicWatchers = bool(false)
+)
+
+func (x *FeatureFlags) Reset() {
+ *x = FeatureFlags{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FeatureFlags) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FeatureFlags) ProtoMessage() {}
+
+func (x *FeatureFlags) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[10]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FeatureFlags.ProtoReflect.Descriptor instead.
+func (*FeatureFlags) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *FeatureFlags) GetSupportsAuthRefresh() bool {
+ if x != nil && x.SupportsAuthRefresh != nil {
+ return *x.SupportsAuthRefresh
+ }
+ return Default_FeatureFlags_SupportsAuthRefresh
+}
+
+func (x *FeatureFlags) GetSupportsBrokerEntryMetadata() bool {
+ if x != nil && x.SupportsBrokerEntryMetadata != nil {
+ return *x.SupportsBrokerEntryMetadata
+ }
+ return Default_FeatureFlags_SupportsBrokerEntryMetadata
+}
+
+func (x *FeatureFlags) GetSupportsPartialProducer() bool {
+ if x != nil && x.SupportsPartialProducer != nil {
+ return *x.SupportsPartialProducer
+ }
+ return Default_FeatureFlags_SupportsPartialProducer
+}
+
+func (x *FeatureFlags) GetSupportsTopicWatchers() bool {
+ if x != nil && x.SupportsTopicWatchers != nil {
+ return *x.SupportsTopicWatchers
+ }
+ return Default_FeatureFlags_SupportsTopicWatchers
+}
+
+type CommandConnected struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ServerVersion *string `protobuf:"bytes,1,req,name=server_version,json=serverVersion" json:"server_version,omitempty"`
+ ProtocolVersion *int32 `protobuf:"varint,2,opt,name=protocol_version,json=protocolVersion,def=0" json:"protocol_version,omitempty"`
+ MaxMessageSize *int32 `protobuf:"varint,3,opt,name=max_message_size,json=maxMessageSize" json:"max_message_size,omitempty"`
+ FeatureFlags *FeatureFlags `protobuf:"bytes,4,opt,name=feature_flags,json=featureFlags" json:"feature_flags,omitempty"`
+}
+
+// Default values for CommandConnected fields.
+const (
+ Default_CommandConnected_ProtocolVersion = int32(0)
+)
+
+func (x *CommandConnected) Reset() {
+ *x = CommandConnected{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandConnected) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandConnected) ProtoMessage() {}
+
+func (x *CommandConnected) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[11]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandConnected.ProtoReflect.Descriptor instead.
+func (*CommandConnected) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *CommandConnected) GetServerVersion() string {
+ if x != nil && x.ServerVersion != nil {
+ return *x.ServerVersion
+ }
+ return ""
+}
+
+func (x *CommandConnected) GetProtocolVersion() int32 {
+ if x != nil && x.ProtocolVersion != nil {
+ return *x.ProtocolVersion
+ }
+ return Default_CommandConnected_ProtocolVersion
+}
+
+func (x *CommandConnected) GetMaxMessageSize() int32 {
+ if x != nil && x.MaxMessageSize != nil {
+ return *x.MaxMessageSize
+ }
+ return 0
+}
+
+func (x *CommandConnected) GetFeatureFlags() *FeatureFlags {
+ if x != nil {
+ return x.FeatureFlags
+ }
+ return nil
+}
+
+type CommandAuthResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClientVersion *string `protobuf:"bytes,1,opt,name=client_version,json=clientVersion" json:"client_version,omitempty"`
+ Response *AuthData `protobuf:"bytes,2,opt,name=response" json:"response,omitempty"`
+ ProtocolVersion *int32 `protobuf:"varint,3,opt,name=protocol_version,json=protocolVersion,def=0" json:"protocol_version,omitempty"`
+}
+
+// Default values for CommandAuthResponse fields.
+const (
+ Default_CommandAuthResponse_ProtocolVersion = int32(0)
+)
+
+func (x *CommandAuthResponse) Reset() {
+ *x = CommandAuthResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandAuthResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandAuthResponse) ProtoMessage() {}
+
+func (x *CommandAuthResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[12]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandAuthResponse.ProtoReflect.Descriptor instead.
+func (*CommandAuthResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *CommandAuthResponse) GetClientVersion() string {
+ if x != nil && x.ClientVersion != nil {
+ return *x.ClientVersion
+ }
+ return ""
+}
+
+func (x *CommandAuthResponse) GetResponse() *AuthData {
+ if x != nil {
+ return x.Response
+ }
+ return nil
+}
+
+func (x *CommandAuthResponse) GetProtocolVersion() int32 {
+ if x != nil && x.ProtocolVersion != nil {
+ return *x.ProtocolVersion
+ }
+ return Default_CommandAuthResponse_ProtocolVersion
+}
+
+type CommandAuthChallenge struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ServerVersion *string `protobuf:"bytes,1,opt,name=server_version,json=serverVersion" json:"server_version,omitempty"`
+ Challenge *AuthData `protobuf:"bytes,2,opt,name=challenge" json:"challenge,omitempty"`
+ ProtocolVersion *int32 `protobuf:"varint,3,opt,name=protocol_version,json=protocolVersion,def=0" json:"protocol_version,omitempty"`
+}
+
+// Default values for CommandAuthChallenge fields.
+const (
+ Default_CommandAuthChallenge_ProtocolVersion = int32(0)
+)
+
+func (x *CommandAuthChallenge) Reset() {
+ *x = CommandAuthChallenge{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[13]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandAuthChallenge) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandAuthChallenge) ProtoMessage() {}
+
+func (x *CommandAuthChallenge) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[13]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandAuthChallenge.ProtoReflect.Descriptor instead.
+func (*CommandAuthChallenge) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *CommandAuthChallenge) GetServerVersion() string {
+ if x != nil && x.ServerVersion != nil {
+ return *x.ServerVersion
+ }
+ return ""
+}
+
+func (x *CommandAuthChallenge) GetChallenge() *AuthData {
+ if x != nil {
+ return x.Challenge
+ }
+ return nil
+}
+
+func (x *CommandAuthChallenge) GetProtocolVersion() int32 {
+ if x != nil && x.ProtocolVersion != nil {
+ return *x.ProtocolVersion
+ }
+ return Default_CommandAuthChallenge_ProtocolVersion
+}
+
+// To support mutual authentication type, such as Sasl, reuse this command to mutual auth.
+type AuthData struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AuthMethodName *string `protobuf:"bytes,1,opt,name=auth_method_name,json=authMethodName" json:"auth_method_name,omitempty"`
+ AuthData []byte `protobuf:"bytes,2,opt,name=auth_data,json=authData" json:"auth_data,omitempty"`
+}
+
+func (x *AuthData) Reset() {
+ *x = AuthData{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[14]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AuthData) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AuthData) ProtoMessage() {}
+
+func (x *AuthData) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[14]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AuthData.ProtoReflect.Descriptor instead.
+func (*AuthData) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{14}
+}
+
+func (x *AuthData) GetAuthMethodName() string {
+ if x != nil && x.AuthMethodName != nil {
+ return *x.AuthMethodName
+ }
+ return ""
+}
+
+func (x *AuthData) GetAuthData() []byte {
+ if x != nil {
+ return x.AuthData
+ }
+ return nil
+}
+
+type KeySharedMeta struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ KeySharedMode *KeySharedMode `protobuf:"varint,1,req,name=keySharedMode,enum=pulsar.proto.KeySharedMode" json:"keySharedMode,omitempty"`
+ HashRanges []*IntRange `protobuf:"bytes,3,rep,name=hashRanges" json:"hashRanges,omitempty"`
+ AllowOutOfOrderDelivery *bool `protobuf:"varint,4,opt,name=allowOutOfOrderDelivery,def=0" json:"allowOutOfOrderDelivery,omitempty"`
+}
+
+// Default values for KeySharedMeta fields.
+const (
+ Default_KeySharedMeta_AllowOutOfOrderDelivery = bool(false)
+)
+
+func (x *KeySharedMeta) Reset() {
+ *x = KeySharedMeta{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[15]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *KeySharedMeta) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*KeySharedMeta) ProtoMessage() {}
+
+func (x *KeySharedMeta) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[15]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use KeySharedMeta.ProtoReflect.Descriptor instead.
+func (*KeySharedMeta) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{15}
+}
+
+func (x *KeySharedMeta) GetKeySharedMode() KeySharedMode {
+ if x != nil && x.KeySharedMode != nil {
+ return *x.KeySharedMode
+ }
+ return KeySharedMode_AUTO_SPLIT
+}
+
+func (x *KeySharedMeta) GetHashRanges() []*IntRange {
+ if x != nil {
+ return x.HashRanges
+ }
+ return nil
+}
+
+func (x *KeySharedMeta) GetAllowOutOfOrderDelivery() bool {
+ if x != nil && x.AllowOutOfOrderDelivery != nil {
+ return *x.AllowOutOfOrderDelivery
+ }
+ return Default_KeySharedMeta_AllowOutOfOrderDelivery
+}
+
+type CommandSubscribe struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Topic *string `protobuf:"bytes,1,req,name=topic" json:"topic,omitempty"`
+ Subscription *string `protobuf:"bytes,2,req,name=subscription" json:"subscription,omitempty"`
+ SubType *CommandSubscribe_SubType `protobuf:"varint,3,req,name=subType,enum=pulsar.proto.CommandSubscribe_SubType" json:"subType,omitempty"`
+ ConsumerId *uint64 `protobuf:"varint,4,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ RequestId *uint64 `protobuf:"varint,5,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ ConsumerName *string `protobuf:"bytes,6,opt,name=consumer_name,json=consumerName" json:"consumer_name,omitempty"`
+ PriorityLevel *int32 `protobuf:"varint,7,opt,name=priority_level,json=priorityLevel" json:"priority_level,omitempty"`
+ // Signal wether the subscription should be backed by a
+ // durable cursor or not
+ Durable *bool `protobuf:"varint,8,opt,name=durable,def=1" json:"durable,omitempty"`
+ // If specified, the subscription will position the cursor
+ // markd-delete position on the particular message id and
+ // will send messages from that point
+ StartMessageId *MessageIdData `protobuf:"bytes,9,opt,name=start_message_id,json=startMessageId" json:"start_message_id,omitempty"`
+ /// Add optional metadata key=value to this consumer
+ Metadata []*KeyValue `protobuf:"bytes,10,rep,name=metadata" json:"metadata,omitempty"`
+ ReadCompacted *bool `protobuf:"varint,11,opt,name=read_compacted,json=readCompacted" json:"read_compacted,omitempty"`
+ Schema *Schema `protobuf:"bytes,12,opt,name=schema" json:"schema,omitempty"`
+ // Signal whether the subscription will initialize on latest
+ // or not -- earliest
+ InitialPosition *CommandSubscribe_InitialPosition `protobuf:"varint,13,opt,name=initialPosition,enum=pulsar.proto.CommandSubscribe_InitialPosition,def=0" json:"initialPosition,omitempty"`
+ // Mark the subscription as "replicated". Pulsar will make sure
+ // to periodically sync the state of replicated subscriptions
+ // across different clusters (when using geo-replication).
+ ReplicateSubscriptionState *bool `protobuf:"varint,14,opt,name=replicate_subscription_state,json=replicateSubscriptionState" json:"replicate_subscription_state,omitempty"`
+ // If true, the subscribe operation will cause a topic to be
+ // created if it does not exist already (and if topic auto-creation
+ // is allowed by broker.
+ // If false, the subscribe operation will fail if the topic
+ // does not exist.
+ ForceTopicCreation *bool `protobuf:"varint,15,opt,name=force_topic_creation,json=forceTopicCreation,def=1" json:"force_topic_creation,omitempty"`
+ // If specified, the subscription will reset cursor's position back
+ // to specified seconds and will send messages from that point
+ StartMessageRollbackDurationSec *uint64 `protobuf:"varint,16,opt,name=start_message_rollback_duration_sec,json=startMessageRollbackDurationSec,def=0" json:"start_message_rollback_duration_sec,omitempty"`
+ KeySharedMeta *KeySharedMeta `protobuf:"bytes,17,opt,name=keySharedMeta" json:"keySharedMeta,omitempty"`
+ SubscriptionProperties []*KeyValue `protobuf:"bytes,18,rep,name=subscription_properties,json=subscriptionProperties" json:"subscription_properties,omitempty"`
+ // The consumer epoch, when exclusive and failover consumer redeliver unack message will increase the epoch
+ ConsumerEpoch *uint64 `protobuf:"varint,19,opt,name=consumer_epoch,json=consumerEpoch" json:"consumer_epoch,omitempty"`
+}
+
+// Default values for CommandSubscribe fields.
+const (
+ Default_CommandSubscribe_Durable = bool(true)
+ Default_CommandSubscribe_InitialPosition = CommandSubscribe_Latest
+ Default_CommandSubscribe_ForceTopicCreation = bool(true)
+ Default_CommandSubscribe_StartMessageRollbackDurationSec = uint64(0)
+)
+
+func (x *CommandSubscribe) Reset() {
+ *x = CommandSubscribe{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[16]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandSubscribe) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandSubscribe) ProtoMessage() {}
+
+func (x *CommandSubscribe) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[16]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandSubscribe.ProtoReflect.Descriptor instead.
+func (*CommandSubscribe) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *CommandSubscribe) GetTopic() string {
+ if x != nil && x.Topic != nil {
+ return *x.Topic
+ }
+ return ""
+}
+
+func (x *CommandSubscribe) GetSubscription() string {
+ if x != nil && x.Subscription != nil {
+ return *x.Subscription
+ }
+ return ""
+}
+
+func (x *CommandSubscribe) GetSubType() CommandSubscribe_SubType {
+ if x != nil && x.SubType != nil {
+ return *x.SubType
+ }
+ return CommandSubscribe_Exclusive
+}
+
+func (x *CommandSubscribe) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandSubscribe) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandSubscribe) GetConsumerName() string {
+ if x != nil && x.ConsumerName != nil {
+ return *x.ConsumerName
+ }
+ return ""
+}
+
+func (x *CommandSubscribe) GetPriorityLevel() int32 {
+ if x != nil && x.PriorityLevel != nil {
+ return *x.PriorityLevel
+ }
+ return 0
+}
+
+func (x *CommandSubscribe) GetDurable() bool {
+ if x != nil && x.Durable != nil {
+ return *x.Durable
+ }
+ return Default_CommandSubscribe_Durable
+}
+
+func (x *CommandSubscribe) GetStartMessageId() *MessageIdData {
+ if x != nil {
+ return x.StartMessageId
+ }
+ return nil
+}
+
+func (x *CommandSubscribe) GetMetadata() []*KeyValue {
+ if x != nil {
+ return x.Metadata
+ }
+ return nil
+}
+
+func (x *CommandSubscribe) GetReadCompacted() bool {
+ if x != nil && x.ReadCompacted != nil {
+ return *x.ReadCompacted
+ }
+ return false
+}
+
+func (x *CommandSubscribe) GetSchema() *Schema {
+ if x != nil {
+ return x.Schema
+ }
+ return nil
+}
+
+func (x *CommandSubscribe) GetInitialPosition() CommandSubscribe_InitialPosition {
+ if x != nil && x.InitialPosition != nil {
+ return *x.InitialPosition
+ }
+ return Default_CommandSubscribe_InitialPosition
+}
+
+func (x *CommandSubscribe) GetReplicateSubscriptionState() bool {
+ if x != nil && x.ReplicateSubscriptionState != nil {
+ return *x.ReplicateSubscriptionState
+ }
+ return false
+}
+
+func (x *CommandSubscribe) GetForceTopicCreation() bool {
+ if x != nil && x.ForceTopicCreation != nil {
+ return *x.ForceTopicCreation
+ }
+ return Default_CommandSubscribe_ForceTopicCreation
+}
+
+func (x *CommandSubscribe) GetStartMessageRollbackDurationSec() uint64 {
+ if x != nil && x.StartMessageRollbackDurationSec != nil {
+ return *x.StartMessageRollbackDurationSec
+ }
+ return Default_CommandSubscribe_StartMessageRollbackDurationSec
+}
+
+func (x *CommandSubscribe) GetKeySharedMeta() *KeySharedMeta {
+ if x != nil {
+ return x.KeySharedMeta
+ }
+ return nil
+}
+
+func (x *CommandSubscribe) GetSubscriptionProperties() []*KeyValue {
+ if x != nil {
+ return x.SubscriptionProperties
+ }
+ return nil
+}
+
+func (x *CommandSubscribe) GetConsumerEpoch() uint64 {
+ if x != nil && x.ConsumerEpoch != nil {
+ return *x.ConsumerEpoch
+ }
+ return 0
+}
+
+type CommandPartitionedTopicMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Topic *string `protobuf:"bytes,1,req,name=topic" json:"topic,omitempty"`
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ // TODO - Remove original_principal, original_auth_data, original_auth_method
+ // Original principal that was verified by
+ // a Pulsar proxy.
+ OriginalPrincipal *string `protobuf:"bytes,3,opt,name=original_principal,json=originalPrincipal" json:"original_principal,omitempty"`
+ // Original auth role and auth Method that was passed
+ // to the proxy.
+ OriginalAuthData *string `protobuf:"bytes,4,opt,name=original_auth_data,json=originalAuthData" json:"original_auth_data,omitempty"`
+ OriginalAuthMethod *string `protobuf:"bytes,5,opt,name=original_auth_method,json=originalAuthMethod" json:"original_auth_method,omitempty"`
+}
+
+func (x *CommandPartitionedTopicMetadata) Reset() {
+ *x = CommandPartitionedTopicMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[17]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandPartitionedTopicMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandPartitionedTopicMetadata) ProtoMessage() {}
+
+func (x *CommandPartitionedTopicMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[17]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandPartitionedTopicMetadata.ProtoReflect.Descriptor instead.
+func (*CommandPartitionedTopicMetadata) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{17}
+}
+
+func (x *CommandPartitionedTopicMetadata) GetTopic() string {
+ if x != nil && x.Topic != nil {
+ return *x.Topic
+ }
+ return ""
+}
+
+func (x *CommandPartitionedTopicMetadata) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandPartitionedTopicMetadata) GetOriginalPrincipal() string {
+ if x != nil && x.OriginalPrincipal != nil {
+ return *x.OriginalPrincipal
+ }
+ return ""
+}
+
+func (x *CommandPartitionedTopicMetadata) GetOriginalAuthData() string {
+ if x != nil && x.OriginalAuthData != nil {
+ return *x.OriginalAuthData
+ }
+ return ""
+}
+
+func (x *CommandPartitionedTopicMetadata) GetOriginalAuthMethod() string {
+ if x != nil && x.OriginalAuthMethod != nil {
+ return *x.OriginalAuthMethod
+ }
+ return ""
+}
+
+type CommandPartitionedTopicMetadataResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Partitions *uint32 `protobuf:"varint,1,opt,name=partitions" json:"partitions,omitempty"` // Optional in case of error
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Response *CommandPartitionedTopicMetadataResponse_LookupType `protobuf:"varint,3,opt,name=response,enum=pulsar.proto.CommandPartitionedTopicMetadataResponse_LookupType" json:"response,omitempty"`
+ Error *ServerError `protobuf:"varint,4,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"`
+}
+
+func (x *CommandPartitionedTopicMetadataResponse) Reset() {
+ *x = CommandPartitionedTopicMetadataResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[18]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandPartitionedTopicMetadataResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandPartitionedTopicMetadataResponse) ProtoMessage() {}
+
+func (x *CommandPartitionedTopicMetadataResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[18]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandPartitionedTopicMetadataResponse.ProtoReflect.Descriptor instead.
+func (*CommandPartitionedTopicMetadataResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *CommandPartitionedTopicMetadataResponse) GetPartitions() uint32 {
+ if x != nil && x.Partitions != nil {
+ return *x.Partitions
+ }
+ return 0
+}
+
+func (x *CommandPartitionedTopicMetadataResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandPartitionedTopicMetadataResponse) GetResponse() CommandPartitionedTopicMetadataResponse_LookupType {
+ if x != nil && x.Response != nil {
+ return *x.Response
+ }
+ return CommandPartitionedTopicMetadataResponse_Success
+}
+
+func (x *CommandPartitionedTopicMetadataResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandPartitionedTopicMetadataResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type CommandLookupTopic struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Topic *string `protobuf:"bytes,1,req,name=topic" json:"topic,omitempty"`
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Authoritative *bool `protobuf:"varint,3,opt,name=authoritative,def=0" json:"authoritative,omitempty"`
+ // TODO - Remove original_principal, original_auth_data, original_auth_method
+ // Original principal that was verified by
+ // a Pulsar proxy.
+ OriginalPrincipal *string `protobuf:"bytes,4,opt,name=original_principal,json=originalPrincipal" json:"original_principal,omitempty"`
+ // Original auth role and auth Method that was passed
+ // to the proxy.
+ OriginalAuthData *string `protobuf:"bytes,5,opt,name=original_auth_data,json=originalAuthData" json:"original_auth_data,omitempty"`
+ OriginalAuthMethod *string `protobuf:"bytes,6,opt,name=original_auth_method,json=originalAuthMethod" json:"original_auth_method,omitempty"`
+ //
+ AdvertisedListenerName *string `protobuf:"bytes,7,opt,name=advertised_listener_name,json=advertisedListenerName" json:"advertised_listener_name,omitempty"`
+}
+
+// Default values for CommandLookupTopic fields.
+const (
+ Default_CommandLookupTopic_Authoritative = bool(false)
+)
+
+func (x *CommandLookupTopic) Reset() {
+ *x = CommandLookupTopic{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[19]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandLookupTopic) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandLookupTopic) ProtoMessage() {}
+
+func (x *CommandLookupTopic) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[19]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandLookupTopic.ProtoReflect.Descriptor instead.
+func (*CommandLookupTopic) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *CommandLookupTopic) GetTopic() string {
+ if x != nil && x.Topic != nil {
+ return *x.Topic
+ }
+ return ""
+}
+
+func (x *CommandLookupTopic) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandLookupTopic) GetAuthoritative() bool {
+ if x != nil && x.Authoritative != nil {
+ return *x.Authoritative
+ }
+ return Default_CommandLookupTopic_Authoritative
+}
+
+func (x *CommandLookupTopic) GetOriginalPrincipal() string {
+ if x != nil && x.OriginalPrincipal != nil {
+ return *x.OriginalPrincipal
+ }
+ return ""
+}
+
+func (x *CommandLookupTopic) GetOriginalAuthData() string {
+ if x != nil && x.OriginalAuthData != nil {
+ return *x.OriginalAuthData
+ }
+ return ""
+}
+
+func (x *CommandLookupTopic) GetOriginalAuthMethod() string {
+ if x != nil && x.OriginalAuthMethod != nil {
+ return *x.OriginalAuthMethod
+ }
+ return ""
+}
+
+func (x *CommandLookupTopic) GetAdvertisedListenerName() string {
+ if x != nil && x.AdvertisedListenerName != nil {
+ return *x.AdvertisedListenerName
+ }
+ return ""
+}
+
+type CommandLookupTopicResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ BrokerServiceUrl *string `protobuf:"bytes,1,opt,name=brokerServiceUrl" json:"brokerServiceUrl,omitempty"` // Optional in case of error
+ BrokerServiceUrlTls *string `protobuf:"bytes,2,opt,name=brokerServiceUrlTls" json:"brokerServiceUrlTls,omitempty"`
+ Response *CommandLookupTopicResponse_LookupType `protobuf:"varint,3,opt,name=response,enum=pulsar.proto.CommandLookupTopicResponse_LookupType" json:"response,omitempty"`
+ RequestId *uint64 `protobuf:"varint,4,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Authoritative *bool `protobuf:"varint,5,opt,name=authoritative,def=0" json:"authoritative,omitempty"`
+ Error *ServerError `protobuf:"varint,6,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,7,opt,name=message" json:"message,omitempty"`
+ // If it's true, indicates to the client that it must
+ // always connect through the service url after the
+ // lookup has been completed.
+ ProxyThroughServiceUrl *bool `protobuf:"varint,8,opt,name=proxy_through_service_url,json=proxyThroughServiceUrl,def=0" json:"proxy_through_service_url,omitempty"`
+}
+
+// Default values for CommandLookupTopicResponse fields.
+const (
+ Default_CommandLookupTopicResponse_Authoritative = bool(false)
+ Default_CommandLookupTopicResponse_ProxyThroughServiceUrl = bool(false)
+)
+
+func (x *CommandLookupTopicResponse) Reset() {
+ *x = CommandLookupTopicResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[20]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandLookupTopicResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandLookupTopicResponse) ProtoMessage() {}
+
+func (x *CommandLookupTopicResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[20]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandLookupTopicResponse.ProtoReflect.Descriptor instead.
+func (*CommandLookupTopicResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *CommandLookupTopicResponse) GetBrokerServiceUrl() string {
+ if x != nil && x.BrokerServiceUrl != nil {
+ return *x.BrokerServiceUrl
+ }
+ return ""
+}
+
+func (x *CommandLookupTopicResponse) GetBrokerServiceUrlTls() string {
+ if x != nil && x.BrokerServiceUrlTls != nil {
+ return *x.BrokerServiceUrlTls
+ }
+ return ""
+}
+
+func (x *CommandLookupTopicResponse) GetResponse() CommandLookupTopicResponse_LookupType {
+ if x != nil && x.Response != nil {
+ return *x.Response
+ }
+ return CommandLookupTopicResponse_Redirect
+}
+
+func (x *CommandLookupTopicResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandLookupTopicResponse) GetAuthoritative() bool {
+ if x != nil && x.Authoritative != nil {
+ return *x.Authoritative
+ }
+ return Default_CommandLookupTopicResponse_Authoritative
+}
+
+func (x *CommandLookupTopicResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandLookupTopicResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+func (x *CommandLookupTopicResponse) GetProxyThroughServiceUrl() bool {
+ if x != nil && x.ProxyThroughServiceUrl != nil {
+ return *x.ProxyThroughServiceUrl
+ }
+ return Default_CommandLookupTopicResponse_ProxyThroughServiceUrl
+}
+
+/// Create a new Producer on a topic, assigning the given producer_id,
+/// all messages sent with this producer_id will be persisted on the topic
+type CommandProducer struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Topic *string `protobuf:"bytes,1,req,name=topic" json:"topic,omitempty"`
+ ProducerId *uint64 `protobuf:"varint,2,req,name=producer_id,json=producerId" json:"producer_id,omitempty"`
+ RequestId *uint64 `protobuf:"varint,3,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ /// If a producer name is specified, the name will be used,
+ /// otherwise the broker will generate a unique name
+ ProducerName *string `protobuf:"bytes,4,opt,name=producer_name,json=producerName" json:"producer_name,omitempty"`
+ Encrypted *bool `protobuf:"varint,5,opt,name=encrypted,def=0" json:"encrypted,omitempty"`
+ /// Add optional metadata key=value to this producer
+ Metadata []*KeyValue `protobuf:"bytes,6,rep,name=metadata" json:"metadata,omitempty"`
+ Schema *Schema `protobuf:"bytes,7,opt,name=schema" json:"schema,omitempty"`
+ // If producer reconnect to broker, the epoch of this producer will +1
+ Epoch *uint64 `protobuf:"varint,8,opt,name=epoch,def=0" json:"epoch,omitempty"`
+ // Indicate the name of the producer is generated or user provided
+ // Use default true here is in order to be forward compatible with the client
+ UserProvidedProducerName *bool `protobuf:"varint,9,opt,name=user_provided_producer_name,json=userProvidedProducerName,def=1" json:"user_provided_producer_name,omitempty"`
+ // Require that this producers will be the only producer allowed on the topic
+ ProducerAccessMode *ProducerAccessMode `protobuf:"varint,10,opt,name=producer_access_mode,json=producerAccessMode,enum=pulsar.proto.ProducerAccessMode,def=0" json:"producer_access_mode,omitempty"`
+ // Topic epoch is used to fence off producers that reconnects after a new
+ // exclusive producer has already taken over. This id is assigned by the
+ // broker on the CommandProducerSuccess. The first time, the client will
+ // leave it empty and then it will always carry the same epoch number on
+ // the subsequent reconnections.
+ TopicEpoch *uint64 `protobuf:"varint,11,opt,name=topic_epoch,json=topicEpoch" json:"topic_epoch,omitempty"`
+ TxnEnabled *bool `protobuf:"varint,12,opt,name=txn_enabled,json=txnEnabled,def=0" json:"txn_enabled,omitempty"`
+ // Name of the initial subscription of the topic.
+ // If this field is not set, the initial subscription will not be created.
+ // If this field is set but the broker's `allowAutoSubscriptionCreation`
+ // is disabled, the producer will fail to be created.
+ InitialSubscriptionName *string `protobuf:"bytes,13,opt,name=initial_subscription_name,json=initialSubscriptionName" json:"initial_subscription_name,omitempty"`
+}
+
+// Default values for CommandProducer fields.
+const (
+ Default_CommandProducer_Encrypted = bool(false)
+ Default_CommandProducer_Epoch = uint64(0)
+ Default_CommandProducer_UserProvidedProducerName = bool(true)
+ Default_CommandProducer_ProducerAccessMode = ProducerAccessMode_Shared
+ Default_CommandProducer_TxnEnabled = bool(false)
+)
+
+func (x *CommandProducer) Reset() {
+ *x = CommandProducer{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[21]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandProducer) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandProducer) ProtoMessage() {}
+
+func (x *CommandProducer) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[21]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandProducer.ProtoReflect.Descriptor instead.
+func (*CommandProducer) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{21}
+}
+
+func (x *CommandProducer) GetTopic() string {
+ if x != nil && x.Topic != nil {
+ return *x.Topic
+ }
+ return ""
+}
+
+func (x *CommandProducer) GetProducerId() uint64 {
+ if x != nil && x.ProducerId != nil {
+ return *x.ProducerId
+ }
+ return 0
+}
+
+func (x *CommandProducer) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandProducer) GetProducerName() string {
+ if x != nil && x.ProducerName != nil {
+ return *x.ProducerName
+ }
+ return ""
+}
+
+func (x *CommandProducer) GetEncrypted() bool {
+ if x != nil && x.Encrypted != nil {
+ return *x.Encrypted
+ }
+ return Default_CommandProducer_Encrypted
+}
+
+func (x *CommandProducer) GetMetadata() []*KeyValue {
+ if x != nil {
+ return x.Metadata
+ }
+ return nil
+}
+
+func (x *CommandProducer) GetSchema() *Schema {
+ if x != nil {
+ return x.Schema
+ }
+ return nil
+}
+
+func (x *CommandProducer) GetEpoch() uint64 {
+ if x != nil && x.Epoch != nil {
+ return *x.Epoch
+ }
+ return Default_CommandProducer_Epoch
+}
+
+func (x *CommandProducer) GetUserProvidedProducerName() bool {
+ if x != nil && x.UserProvidedProducerName != nil {
+ return *x.UserProvidedProducerName
+ }
+ return Default_CommandProducer_UserProvidedProducerName
+}
+
+func (x *CommandProducer) GetProducerAccessMode() ProducerAccessMode {
+ if x != nil && x.ProducerAccessMode != nil {
+ return *x.ProducerAccessMode
+ }
+ return Default_CommandProducer_ProducerAccessMode
+}
+
+func (x *CommandProducer) GetTopicEpoch() uint64 {
+ if x != nil && x.TopicEpoch != nil {
+ return *x.TopicEpoch
+ }
+ return 0
+}
+
+func (x *CommandProducer) GetTxnEnabled() bool {
+ if x != nil && x.TxnEnabled != nil {
+ return *x.TxnEnabled
+ }
+ return Default_CommandProducer_TxnEnabled
+}
+
+func (x *CommandProducer) GetInitialSubscriptionName() string {
+ if x != nil && x.InitialSubscriptionName != nil {
+ return *x.InitialSubscriptionName
+ }
+ return ""
+}
+
+type CommandSend struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ProducerId *uint64 `protobuf:"varint,1,req,name=producer_id,json=producerId" json:"producer_id,omitempty"`
+ SequenceId *uint64 `protobuf:"varint,2,req,name=sequence_id,json=sequenceId" json:"sequence_id,omitempty"`
+ NumMessages *int32 `protobuf:"varint,3,opt,name=num_messages,json=numMessages,def=1" json:"num_messages,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,4,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,5,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ /// Add highest sequence id to support batch message with external sequence id
+ HighestSequenceId *uint64 `protobuf:"varint,6,opt,name=highest_sequence_id,json=highestSequenceId,def=0" json:"highest_sequence_id,omitempty"`
+ IsChunk *bool `protobuf:"varint,7,opt,name=is_chunk,json=isChunk,def=0" json:"is_chunk,omitempty"`
+ // Specify if the message being published is a Pulsar marker or not
+ Marker *bool `protobuf:"varint,8,opt,name=marker,def=0" json:"marker,omitempty"`
+ // Message id of this message, currently is used in replicator for shadow topic.
+ MessageId *MessageIdData `protobuf:"bytes,9,opt,name=message_id,json=messageId" json:"message_id,omitempty"`
+}
+
+// Default values for CommandSend fields.
+const (
+ Default_CommandSend_NumMessages = int32(1)
+ Default_CommandSend_TxnidLeastBits = uint64(0)
+ Default_CommandSend_TxnidMostBits = uint64(0)
+ Default_CommandSend_HighestSequenceId = uint64(0)
+ Default_CommandSend_IsChunk = bool(false)
+ Default_CommandSend_Marker = bool(false)
+)
+
+func (x *CommandSend) Reset() {
+ *x = CommandSend{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[22]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandSend) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandSend) ProtoMessage() {}
+
+func (x *CommandSend) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[22]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandSend.ProtoReflect.Descriptor instead.
+func (*CommandSend) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{22}
+}
+
+func (x *CommandSend) GetProducerId() uint64 {
+ if x != nil && x.ProducerId != nil {
+ return *x.ProducerId
+ }
+ return 0
+}
+
+func (x *CommandSend) GetSequenceId() uint64 {
+ if x != nil && x.SequenceId != nil {
+ return *x.SequenceId
+ }
+ return 0
+}
+
+func (x *CommandSend) GetNumMessages() int32 {
+ if x != nil && x.NumMessages != nil {
+ return *x.NumMessages
+ }
+ return Default_CommandSend_NumMessages
+}
+
+func (x *CommandSend) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandSend_TxnidLeastBits
+}
+
+func (x *CommandSend) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandSend_TxnidMostBits
+}
+
+func (x *CommandSend) GetHighestSequenceId() uint64 {
+ if x != nil && x.HighestSequenceId != nil {
+ return *x.HighestSequenceId
+ }
+ return Default_CommandSend_HighestSequenceId
+}
+
+func (x *CommandSend) GetIsChunk() bool {
+ if x != nil && x.IsChunk != nil {
+ return *x.IsChunk
+ }
+ return Default_CommandSend_IsChunk
+}
+
+func (x *CommandSend) GetMarker() bool {
+ if x != nil && x.Marker != nil {
+ return *x.Marker
+ }
+ return Default_CommandSend_Marker
+}
+
+func (x *CommandSend) GetMessageId() *MessageIdData {
+ if x != nil {
+ return x.MessageId
+ }
+ return nil
+}
+
+type CommandSendReceipt struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ProducerId *uint64 `protobuf:"varint,1,req,name=producer_id,json=producerId" json:"producer_id,omitempty"`
+ SequenceId *uint64 `protobuf:"varint,2,req,name=sequence_id,json=sequenceId" json:"sequence_id,omitempty"`
+ MessageId *MessageIdData `protobuf:"bytes,3,opt,name=message_id,json=messageId" json:"message_id,omitempty"`
+ HighestSequenceId *uint64 `protobuf:"varint,4,opt,name=highest_sequence_id,json=highestSequenceId,def=0" json:"highest_sequence_id,omitempty"`
+}
+
+// Default values for CommandSendReceipt fields.
+const (
+ Default_CommandSendReceipt_HighestSequenceId = uint64(0)
+)
+
+func (x *CommandSendReceipt) Reset() {
+ *x = CommandSendReceipt{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[23]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandSendReceipt) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandSendReceipt) ProtoMessage() {}
+
+func (x *CommandSendReceipt) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[23]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandSendReceipt.ProtoReflect.Descriptor instead.
+func (*CommandSendReceipt) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{23}
+}
+
+func (x *CommandSendReceipt) GetProducerId() uint64 {
+ if x != nil && x.ProducerId != nil {
+ return *x.ProducerId
+ }
+ return 0
+}
+
+func (x *CommandSendReceipt) GetSequenceId() uint64 {
+ if x != nil && x.SequenceId != nil {
+ return *x.SequenceId
+ }
+ return 0
+}
+
+func (x *CommandSendReceipt) GetMessageId() *MessageIdData {
+ if x != nil {
+ return x.MessageId
+ }
+ return nil
+}
+
+func (x *CommandSendReceipt) GetHighestSequenceId() uint64 {
+ if x != nil && x.HighestSequenceId != nil {
+ return *x.HighestSequenceId
+ }
+ return Default_CommandSendReceipt_HighestSequenceId
+}
+
+type CommandSendError struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ProducerId *uint64 `protobuf:"varint,1,req,name=producer_id,json=producerId" json:"producer_id,omitempty"`
+ SequenceId *uint64 `protobuf:"varint,2,req,name=sequence_id,json=sequenceId" json:"sequence_id,omitempty"`
+ Error *ServerError `protobuf:"varint,3,req,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,4,req,name=message" json:"message,omitempty"`
+}
+
+func (x *CommandSendError) Reset() {
+ *x = CommandSendError{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[24]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandSendError) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandSendError) ProtoMessage() {}
+
+func (x *CommandSendError) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[24]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandSendError.ProtoReflect.Descriptor instead.
+func (*CommandSendError) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{24}
+}
+
+func (x *CommandSendError) GetProducerId() uint64 {
+ if x != nil && x.ProducerId != nil {
+ return *x.ProducerId
+ }
+ return 0
+}
+
+func (x *CommandSendError) GetSequenceId() uint64 {
+ if x != nil && x.SequenceId != nil {
+ return *x.SequenceId
+ }
+ return 0
+}
+
+func (x *CommandSendError) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandSendError) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type CommandMessage struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ MessageId *MessageIdData `protobuf:"bytes,2,req,name=message_id,json=messageId" json:"message_id,omitempty"`
+ RedeliveryCount *uint32 `protobuf:"varint,3,opt,name=redelivery_count,json=redeliveryCount,def=0" json:"redelivery_count,omitempty"`
+ AckSet []int64 `protobuf:"varint,4,rep,name=ack_set,json=ackSet" json:"ack_set,omitempty"`
+ ConsumerEpoch *uint64 `protobuf:"varint,5,opt,name=consumer_epoch,json=consumerEpoch" json:"consumer_epoch,omitempty"`
+}
+
+// Default values for CommandMessage fields.
+const (
+ Default_CommandMessage_RedeliveryCount = uint32(0)
+)
+
+func (x *CommandMessage) Reset() {
+ *x = CommandMessage{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[25]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandMessage) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandMessage) ProtoMessage() {}
+
+func (x *CommandMessage) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[25]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandMessage.ProtoReflect.Descriptor instead.
+func (*CommandMessage) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{25}
+}
+
+func (x *CommandMessage) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandMessage) GetMessageId() *MessageIdData {
+ if x != nil {
+ return x.MessageId
+ }
+ return nil
+}
+
+func (x *CommandMessage) GetRedeliveryCount() uint32 {
+ if x != nil && x.RedeliveryCount != nil {
+ return *x.RedeliveryCount
+ }
+ return Default_CommandMessage_RedeliveryCount
+}
+
+func (x *CommandMessage) GetAckSet() []int64 {
+ if x != nil {
+ return x.AckSet
+ }
+ return nil
+}
+
+func (x *CommandMessage) GetConsumerEpoch() uint64 {
+ if x != nil && x.ConsumerEpoch != nil {
+ return *x.ConsumerEpoch
+ }
+ return 0
+}
+
+type CommandAck struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ AckType *CommandAck_AckType `protobuf:"varint,2,req,name=ack_type,json=ackType,enum=pulsar.proto.CommandAck_AckType" json:"ack_type,omitempty"`
+ // In case of individual acks, the client can pass a list of message ids
+ MessageId []*MessageIdData `protobuf:"bytes,3,rep,name=message_id,json=messageId" json:"message_id,omitempty"`
+ ValidationError *CommandAck_ValidationError `protobuf:"varint,4,opt,name=validation_error,json=validationError,enum=pulsar.proto.CommandAck_ValidationError" json:"validation_error,omitempty"`
+ Properties []*KeyLongValue `protobuf:"bytes,5,rep,name=properties" json:"properties,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,6,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,7,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ RequestId *uint64 `protobuf:"varint,8,opt,name=request_id,json=requestId" json:"request_id,omitempty"`
+}
+
+// Default values for CommandAck fields.
+const (
+ Default_CommandAck_TxnidLeastBits = uint64(0)
+ Default_CommandAck_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandAck) Reset() {
+ *x = CommandAck{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[26]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandAck) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandAck) ProtoMessage() {}
+
+func (x *CommandAck) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[26]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandAck.ProtoReflect.Descriptor instead.
+func (*CommandAck) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{26}
+}
+
+func (x *CommandAck) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandAck) GetAckType() CommandAck_AckType {
+ if x != nil && x.AckType != nil {
+ return *x.AckType
+ }
+ return CommandAck_Individual
+}
+
+func (x *CommandAck) GetMessageId() []*MessageIdData {
+ if x != nil {
+ return x.MessageId
+ }
+ return nil
+}
+
+func (x *CommandAck) GetValidationError() CommandAck_ValidationError {
+ if x != nil && x.ValidationError != nil {
+ return *x.ValidationError
+ }
+ return CommandAck_UncompressedSizeCorruption
+}
+
+func (x *CommandAck) GetProperties() []*KeyLongValue {
+ if x != nil {
+ return x.Properties
+ }
+ return nil
+}
+
+func (x *CommandAck) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandAck_TxnidLeastBits
+}
+
+func (x *CommandAck) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandAck_TxnidMostBits
+}
+
+func (x *CommandAck) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+type CommandAckResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Error *ServerError `protobuf:"varint,4,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"`
+ RequestId *uint64 `protobuf:"varint,6,opt,name=request_id,json=requestId" json:"request_id,omitempty"`
+}
+
+// Default values for CommandAckResponse fields.
+const (
+ Default_CommandAckResponse_TxnidLeastBits = uint64(0)
+ Default_CommandAckResponse_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandAckResponse) Reset() {
+ *x = CommandAckResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[27]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandAckResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandAckResponse) ProtoMessage() {}
+
+func (x *CommandAckResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[27]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandAckResponse.ProtoReflect.Descriptor instead.
+func (*CommandAckResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{27}
+}
+
+func (x *CommandAckResponse) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandAckResponse) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandAckResponse_TxnidLeastBits
+}
+
+func (x *CommandAckResponse) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandAckResponse_TxnidMostBits
+}
+
+func (x *CommandAckResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandAckResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+func (x *CommandAckResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+// changes on active consumer
+type CommandActiveConsumerChange struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ IsActive *bool `protobuf:"varint,2,opt,name=is_active,json=isActive,def=0" json:"is_active,omitempty"`
+}
+
+// Default values for CommandActiveConsumerChange fields.
+const (
+ Default_CommandActiveConsumerChange_IsActive = bool(false)
+)
+
+func (x *CommandActiveConsumerChange) Reset() {
+ *x = CommandActiveConsumerChange{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[28]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandActiveConsumerChange) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandActiveConsumerChange) ProtoMessage() {}
+
+func (x *CommandActiveConsumerChange) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[28]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandActiveConsumerChange.ProtoReflect.Descriptor instead.
+func (*CommandActiveConsumerChange) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{28}
+}
+
+func (x *CommandActiveConsumerChange) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandActiveConsumerChange) GetIsActive() bool {
+ if x != nil && x.IsActive != nil {
+ return *x.IsActive
+ }
+ return Default_CommandActiveConsumerChange_IsActive
+}
+
+type CommandFlow struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ // Max number of messages to prefetch, in addition
+ // of any number previously specified
+ MessagePermits *uint32 `protobuf:"varint,2,req,name=messagePermits" json:"messagePermits,omitempty"`
+}
+
+func (x *CommandFlow) Reset() {
+ *x = CommandFlow{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[29]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandFlow) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandFlow) ProtoMessage() {}
+
+func (x *CommandFlow) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[29]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandFlow.ProtoReflect.Descriptor instead.
+func (*CommandFlow) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{29}
+}
+
+func (x *CommandFlow) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandFlow) GetMessagePermits() uint32 {
+ if x != nil && x.MessagePermits != nil {
+ return *x.MessagePermits
+ }
+ return 0
+}
+
+type CommandUnsubscribe struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+}
+
+func (x *CommandUnsubscribe) Reset() {
+ *x = CommandUnsubscribe{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[30]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandUnsubscribe) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandUnsubscribe) ProtoMessage() {}
+
+func (x *CommandUnsubscribe) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[30]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandUnsubscribe.ProtoReflect.Descriptor instead.
+func (*CommandUnsubscribe) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{30}
+}
+
+func (x *CommandUnsubscribe) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandUnsubscribe) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+// Reset an existing consumer to a particular message id
+type CommandSeek struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ MessageId *MessageIdData `protobuf:"bytes,3,opt,name=message_id,json=messageId" json:"message_id,omitempty"`
+ MessagePublishTime *uint64 `protobuf:"varint,4,opt,name=message_publish_time,json=messagePublishTime" json:"message_publish_time,omitempty"`
+}
+
+func (x *CommandSeek) Reset() {
+ *x = CommandSeek{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[31]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandSeek) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandSeek) ProtoMessage() {}
+
+func (x *CommandSeek) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[31]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandSeek.ProtoReflect.Descriptor instead.
+func (*CommandSeek) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{31}
+}
+
+func (x *CommandSeek) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandSeek) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandSeek) GetMessageId() *MessageIdData {
+ if x != nil {
+ return x.MessageId
+ }
+ return nil
+}
+
+func (x *CommandSeek) GetMessagePublishTime() uint64 {
+ if x != nil && x.MessagePublishTime != nil {
+ return *x.MessagePublishTime
+ }
+ return 0
+}
+
+// Message sent by broker to client when a topic
+// has been forcefully terminated and there are no more
+// messages left to consume
+type CommandReachedEndOfTopic struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+}
+
+func (x *CommandReachedEndOfTopic) Reset() {
+ *x = CommandReachedEndOfTopic{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[32]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandReachedEndOfTopic) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandReachedEndOfTopic) ProtoMessage() {}
+
+func (x *CommandReachedEndOfTopic) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[32]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandReachedEndOfTopic.ProtoReflect.Descriptor instead.
+func (*CommandReachedEndOfTopic) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{32}
+}
+
+func (x *CommandReachedEndOfTopic) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+type CommandCloseProducer struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ProducerId *uint64 `protobuf:"varint,1,req,name=producer_id,json=producerId" json:"producer_id,omitempty"`
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+}
+
+func (x *CommandCloseProducer) Reset() {
+ *x = CommandCloseProducer{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[33]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandCloseProducer) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandCloseProducer) ProtoMessage() {}
+
+func (x *CommandCloseProducer) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[33]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandCloseProducer.ProtoReflect.Descriptor instead.
+func (*CommandCloseProducer) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{33}
+}
+
+func (x *CommandCloseProducer) GetProducerId() uint64 {
+ if x != nil && x.ProducerId != nil {
+ return *x.ProducerId
+ }
+ return 0
+}
+
+func (x *CommandCloseProducer) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+type CommandCloseConsumer struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+}
+
+func (x *CommandCloseConsumer) Reset() {
+ *x = CommandCloseConsumer{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[34]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandCloseConsumer) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandCloseConsumer) ProtoMessage() {}
+
+func (x *CommandCloseConsumer) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[34]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandCloseConsumer.ProtoReflect.Descriptor instead.
+func (*CommandCloseConsumer) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{34}
+}
+
+func (x *CommandCloseConsumer) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandCloseConsumer) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+type CommandRedeliverUnacknowledgedMessages struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ MessageIds []*MessageIdData `protobuf:"bytes,2,rep,name=message_ids,json=messageIds" json:"message_ids,omitempty"`
+ ConsumerEpoch *uint64 `protobuf:"varint,3,opt,name=consumer_epoch,json=consumerEpoch" json:"consumer_epoch,omitempty"`
+}
+
+func (x *CommandRedeliverUnacknowledgedMessages) Reset() {
+ *x = CommandRedeliverUnacknowledgedMessages{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[35]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandRedeliverUnacknowledgedMessages) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandRedeliverUnacknowledgedMessages) ProtoMessage() {}
+
+func (x *CommandRedeliverUnacknowledgedMessages) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[35]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandRedeliverUnacknowledgedMessages.ProtoReflect.Descriptor instead.
+func (*CommandRedeliverUnacknowledgedMessages) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{35}
+}
+
+func (x *CommandRedeliverUnacknowledgedMessages) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandRedeliverUnacknowledgedMessages) GetMessageIds() []*MessageIdData {
+ if x != nil {
+ return x.MessageIds
+ }
+ return nil
+}
+
+func (x *CommandRedeliverUnacknowledgedMessages) GetConsumerEpoch() uint64 {
+ if x != nil && x.ConsumerEpoch != nil {
+ return *x.ConsumerEpoch
+ }
+ return 0
+}
+
+type CommandSuccess struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Schema *Schema `protobuf:"bytes,2,opt,name=schema" json:"schema,omitempty"`
+}
+
+func (x *CommandSuccess) Reset() {
+ *x = CommandSuccess{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[36]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandSuccess) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandSuccess) ProtoMessage() {}
+
+func (x *CommandSuccess) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[36]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandSuccess.ProtoReflect.Descriptor instead.
+func (*CommandSuccess) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{36}
+}
+
+func (x *CommandSuccess) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandSuccess) GetSchema() *Schema {
+ if x != nil {
+ return x.Schema
+ }
+ return nil
+}
+
+/// Response from CommandProducer
+type CommandProducerSuccess struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ ProducerName *string `protobuf:"bytes,2,req,name=producer_name,json=producerName" json:"producer_name,omitempty"`
+ // The last sequence id that was stored by this producer in the previous session
+ // This will only be meaningful if deduplication has been enabled.
+ LastSequenceId *int64 `protobuf:"varint,3,opt,name=last_sequence_id,json=lastSequenceId,def=-1" json:"last_sequence_id,omitempty"`
+ SchemaVersion []byte `protobuf:"bytes,4,opt,name=schema_version,json=schemaVersion" json:"schema_version,omitempty"`
+ // The topic epoch assigned by the broker. This field will only be set if we
+ // were requiring exclusive access when creating the producer.
+ TopicEpoch *uint64 `protobuf:"varint,5,opt,name=topic_epoch,json=topicEpoch" json:"topic_epoch,omitempty"`
+ // If producer is not "ready", the client will avoid to timeout the request
+ // for creating the producer. Instead it will wait indefinitely until it gets
+ // a subsequent `CommandProducerSuccess` with `producer_ready==true`.
+ ProducerReady *bool `protobuf:"varint,6,opt,name=producer_ready,json=producerReady,def=1" json:"producer_ready,omitempty"`
+}
+
+// Default values for CommandProducerSuccess fields.
+const (
+ Default_CommandProducerSuccess_LastSequenceId = int64(-1)
+ Default_CommandProducerSuccess_ProducerReady = bool(true)
+)
+
+func (x *CommandProducerSuccess) Reset() {
+ *x = CommandProducerSuccess{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[37]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandProducerSuccess) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandProducerSuccess) ProtoMessage() {}
+
+func (x *CommandProducerSuccess) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[37]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandProducerSuccess.ProtoReflect.Descriptor instead.
+func (*CommandProducerSuccess) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{37}
+}
+
+func (x *CommandProducerSuccess) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandProducerSuccess) GetProducerName() string {
+ if x != nil && x.ProducerName != nil {
+ return *x.ProducerName
+ }
+ return ""
+}
+
+func (x *CommandProducerSuccess) GetLastSequenceId() int64 {
+ if x != nil && x.LastSequenceId != nil {
+ return *x.LastSequenceId
+ }
+ return Default_CommandProducerSuccess_LastSequenceId
+}
+
+func (x *CommandProducerSuccess) GetSchemaVersion() []byte {
+ if x != nil {
+ return x.SchemaVersion
+ }
+ return nil
+}
+
+func (x *CommandProducerSuccess) GetTopicEpoch() uint64 {
+ if x != nil && x.TopicEpoch != nil {
+ return *x.TopicEpoch
+ }
+ return 0
+}
+
+func (x *CommandProducerSuccess) GetProducerReady() bool {
+ if x != nil && x.ProducerReady != nil {
+ return *x.ProducerReady
+ }
+ return Default_CommandProducerSuccess_ProducerReady
+}
+
+type CommandError struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Error *ServerError `protobuf:"varint,2,req,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,3,req,name=message" json:"message,omitempty"`
+}
+
+func (x *CommandError) Reset() {
+ *x = CommandError{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[38]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandError) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandError) ProtoMessage() {}
+
+func (x *CommandError) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[38]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandError.ProtoReflect.Descriptor instead.
+func (*CommandError) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{38}
+}
+
+func (x *CommandError) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandError) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandError) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+// Commands to probe the state of connection.
+// When either client or broker doesn't receive commands for certain
+// amount of time, they will send a Ping probe.
+type CommandPing struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *CommandPing) Reset() {
+ *x = CommandPing{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[39]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandPing) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandPing) ProtoMessage() {}
+
+func (x *CommandPing) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[39]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandPing.ProtoReflect.Descriptor instead.
+func (*CommandPing) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{39}
+}
+
+type CommandPong struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *CommandPong) Reset() {
+ *x = CommandPong{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[40]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandPong) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandPong) ProtoMessage() {}
+
+func (x *CommandPong) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[40]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandPong.ProtoReflect.Descriptor instead.
+func (*CommandPong) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{40}
+}
+
+type CommandConsumerStats struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ // required string topic_name = 2;
+ // required string subscription_name = 3;
+ ConsumerId *uint64 `protobuf:"varint,4,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+}
+
+func (x *CommandConsumerStats) Reset() {
+ *x = CommandConsumerStats{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[41]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandConsumerStats) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandConsumerStats) ProtoMessage() {}
+
+func (x *CommandConsumerStats) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[41]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandConsumerStats.ProtoReflect.Descriptor instead.
+func (*CommandConsumerStats) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{41}
+}
+
+func (x *CommandConsumerStats) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandConsumerStats) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+type CommandConsumerStatsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ ErrorCode *ServerError `protobuf:"varint,2,opt,name=error_code,json=errorCode,enum=pulsar.proto.ServerError" json:"error_code,omitempty"`
+ ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage" json:"error_message,omitempty"`
+ /// Total rate of messages delivered to the consumer. msg/s
+ MsgRateOut *float64 `protobuf:"fixed64,4,opt,name=msgRateOut" json:"msgRateOut,omitempty"`
+ /// Total throughput delivered to the consumer. bytes/s
+ MsgThroughputOut *float64 `protobuf:"fixed64,5,opt,name=msgThroughputOut" json:"msgThroughputOut,omitempty"`
+ /// Total rate of messages redelivered by this consumer. msg/s
+ MsgRateRedeliver *float64 `protobuf:"fixed64,6,opt,name=msgRateRedeliver" json:"msgRateRedeliver,omitempty"`
+ /// Name of the consumer
+ ConsumerName *string `protobuf:"bytes,7,opt,name=consumerName" json:"consumerName,omitempty"`
+ /// Number of available message permits for the consumer
+ AvailablePermits *uint64 `protobuf:"varint,8,opt,name=availablePermits" json:"availablePermits,omitempty"`
+ /// Number of unacknowledged messages for the consumer
+ UnackedMessages *uint64 `protobuf:"varint,9,opt,name=unackedMessages" json:"unackedMessages,omitempty"`
+ /// Flag to verify if consumer is blocked due to reaching threshold of unacked messages
+ BlockedConsumerOnUnackedMsgs *bool `protobuf:"varint,10,opt,name=blockedConsumerOnUnackedMsgs" json:"blockedConsumerOnUnackedMsgs,omitempty"`
+ /// Address of this consumer
+ Address *string `protobuf:"bytes,11,opt,name=address" json:"address,omitempty"`
+ /// Timestamp of connection
+ ConnectedSince *string `protobuf:"bytes,12,opt,name=connectedSince" json:"connectedSince,omitempty"`
+ /// Whether this subscription is Exclusive or Shared or Failover
+ Type *string `protobuf:"bytes,13,opt,name=type" json:"type,omitempty"`
+ /// Total rate of messages expired on this subscription. msg/s
+ MsgRateExpired *float64 `protobuf:"fixed64,14,opt,name=msgRateExpired" json:"msgRateExpired,omitempty"`
+ /// Number of messages in the subscription backlog
+ MsgBacklog *uint64 `protobuf:"varint,15,opt,name=msgBacklog" json:"msgBacklog,omitempty"`
+ /// Total rate of messages ack. msg/s
+ MessageAckRate *float64 `protobuf:"fixed64,16,opt,name=messageAckRate" json:"messageAckRate,omitempty"`
+}
+
+func (x *CommandConsumerStatsResponse) Reset() {
+ *x = CommandConsumerStatsResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[42]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandConsumerStatsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandConsumerStatsResponse) ProtoMessage() {}
+
+func (x *CommandConsumerStatsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[42]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandConsumerStatsResponse.ProtoReflect.Descriptor instead.
+func (*CommandConsumerStatsResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{42}
+}
+
+func (x *CommandConsumerStatsResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandConsumerStatsResponse) GetErrorCode() ServerError {
+ if x != nil && x.ErrorCode != nil {
+ return *x.ErrorCode
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandConsumerStatsResponse) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
+func (x *CommandConsumerStatsResponse) GetMsgRateOut() float64 {
+ if x != nil && x.MsgRateOut != nil {
+ return *x.MsgRateOut
+ }
+ return 0
+}
+
+func (x *CommandConsumerStatsResponse) GetMsgThroughputOut() float64 {
+ if x != nil && x.MsgThroughputOut != nil {
+ return *x.MsgThroughputOut
+ }
+ return 0
+}
+
+func (x *CommandConsumerStatsResponse) GetMsgRateRedeliver() float64 {
+ if x != nil && x.MsgRateRedeliver != nil {
+ return *x.MsgRateRedeliver
+ }
+ return 0
+}
+
+func (x *CommandConsumerStatsResponse) GetConsumerName() string {
+ if x != nil && x.ConsumerName != nil {
+ return *x.ConsumerName
+ }
+ return ""
+}
+
+func (x *CommandConsumerStatsResponse) GetAvailablePermits() uint64 {
+ if x != nil && x.AvailablePermits != nil {
+ return *x.AvailablePermits
+ }
+ return 0
+}
+
+func (x *CommandConsumerStatsResponse) GetUnackedMessages() uint64 {
+ if x != nil && x.UnackedMessages != nil {
+ return *x.UnackedMessages
+ }
+ return 0
+}
+
+func (x *CommandConsumerStatsResponse) GetBlockedConsumerOnUnackedMsgs() bool {
+ if x != nil && x.BlockedConsumerOnUnackedMsgs != nil {
+ return *x.BlockedConsumerOnUnackedMsgs
+ }
+ return false
+}
+
+func (x *CommandConsumerStatsResponse) GetAddress() string {
+ if x != nil && x.Address != nil {
+ return *x.Address
+ }
+ return ""
+}
+
+func (x *CommandConsumerStatsResponse) GetConnectedSince() string {
+ if x != nil && x.ConnectedSince != nil {
+ return *x.ConnectedSince
+ }
+ return ""
+}
+
+func (x *CommandConsumerStatsResponse) GetType() string {
+ if x != nil && x.Type != nil {
+ return *x.Type
+ }
+ return ""
+}
+
+func (x *CommandConsumerStatsResponse) GetMsgRateExpired() float64 {
+ if x != nil && x.MsgRateExpired != nil {
+ return *x.MsgRateExpired
+ }
+ return 0
+}
+
+func (x *CommandConsumerStatsResponse) GetMsgBacklog() uint64 {
+ if x != nil && x.MsgBacklog != nil {
+ return *x.MsgBacklog
+ }
+ return 0
+}
+
+func (x *CommandConsumerStatsResponse) GetMessageAckRate() float64 {
+ if x != nil && x.MessageAckRate != nil {
+ return *x.MessageAckRate
+ }
+ return 0
+}
+
+type CommandGetLastMessageId struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ConsumerId *uint64 `protobuf:"varint,1,req,name=consumer_id,json=consumerId" json:"consumer_id,omitempty"`
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+}
+
+func (x *CommandGetLastMessageId) Reset() {
+ *x = CommandGetLastMessageId{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[43]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandGetLastMessageId) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandGetLastMessageId) ProtoMessage() {}
+
+func (x *CommandGetLastMessageId) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[43]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandGetLastMessageId.ProtoReflect.Descriptor instead.
+func (*CommandGetLastMessageId) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{43}
+}
+
+func (x *CommandGetLastMessageId) GetConsumerId() uint64 {
+ if x != nil && x.ConsumerId != nil {
+ return *x.ConsumerId
+ }
+ return 0
+}
+
+func (x *CommandGetLastMessageId) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+type CommandGetLastMessageIdResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ LastMessageId *MessageIdData `protobuf:"bytes,1,req,name=last_message_id,json=lastMessageId" json:"last_message_id,omitempty"`
+ RequestId *uint64 `protobuf:"varint,2,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ ConsumerMarkDeletePosition *MessageIdData `protobuf:"bytes,3,opt,name=consumer_mark_delete_position,json=consumerMarkDeletePosition" json:"consumer_mark_delete_position,omitempty"`
+}
+
+func (x *CommandGetLastMessageIdResponse) Reset() {
+ *x = CommandGetLastMessageIdResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[44]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandGetLastMessageIdResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandGetLastMessageIdResponse) ProtoMessage() {}
+
+func (x *CommandGetLastMessageIdResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[44]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandGetLastMessageIdResponse.ProtoReflect.Descriptor instead.
+func (*CommandGetLastMessageIdResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{44}
+}
+
+func (x *CommandGetLastMessageIdResponse) GetLastMessageId() *MessageIdData {
+ if x != nil {
+ return x.LastMessageId
+ }
+ return nil
+}
+
+func (x *CommandGetLastMessageIdResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandGetLastMessageIdResponse) GetConsumerMarkDeletePosition() *MessageIdData {
+ if x != nil {
+ return x.ConsumerMarkDeletePosition
+ }
+ return nil
+}
+
+type CommandGetTopicsOfNamespace struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Namespace *string `protobuf:"bytes,2,req,name=namespace" json:"namespace,omitempty"`
+ Mode *CommandGetTopicsOfNamespace_Mode `protobuf:"varint,3,opt,name=mode,enum=pulsar.proto.CommandGetTopicsOfNamespace_Mode,def=0" json:"mode,omitempty"`
+ TopicsPattern *string `protobuf:"bytes,4,opt,name=topics_pattern,json=topicsPattern" json:"topics_pattern,omitempty"`
+ TopicsHash *string `protobuf:"bytes,5,opt,name=topics_hash,json=topicsHash" json:"topics_hash,omitempty"`
+}
+
+// Default values for CommandGetTopicsOfNamespace fields.
+const (
+ Default_CommandGetTopicsOfNamespace_Mode = CommandGetTopicsOfNamespace_PERSISTENT
+)
+
+func (x *CommandGetTopicsOfNamespace) Reset() {
+ *x = CommandGetTopicsOfNamespace{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[45]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandGetTopicsOfNamespace) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandGetTopicsOfNamespace) ProtoMessage() {}
+
+func (x *CommandGetTopicsOfNamespace) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[45]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandGetTopicsOfNamespace.ProtoReflect.Descriptor instead.
+func (*CommandGetTopicsOfNamespace) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{45}
+}
+
+func (x *CommandGetTopicsOfNamespace) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandGetTopicsOfNamespace) GetNamespace() string {
+ if x != nil && x.Namespace != nil {
+ return *x.Namespace
+ }
+ return ""
+}
+
+func (x *CommandGetTopicsOfNamespace) GetMode() CommandGetTopicsOfNamespace_Mode {
+ if x != nil && x.Mode != nil {
+ return *x.Mode
+ }
+ return Default_CommandGetTopicsOfNamespace_Mode
+}
+
+func (x *CommandGetTopicsOfNamespace) GetTopicsPattern() string {
+ if x != nil && x.TopicsPattern != nil {
+ return *x.TopicsPattern
+ }
+ return ""
+}
+
+func (x *CommandGetTopicsOfNamespace) GetTopicsHash() string {
+ if x != nil && x.TopicsHash != nil {
+ return *x.TopicsHash
+ }
+ return ""
+}
+
+type CommandGetTopicsOfNamespaceResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Topics []string `protobuf:"bytes,2,rep,name=topics" json:"topics,omitempty"`
+ // true iff the topic list was filtered by the pattern supplied by the client
+ Filtered *bool `protobuf:"varint,3,opt,name=filtered,def=0" json:"filtered,omitempty"`
+ // hash computed from the names of matching topics
+ TopicsHash *string `protobuf:"bytes,4,opt,name=topics_hash,json=topicsHash" json:"topics_hash,omitempty"`
+ // if false, topics is empty and the list of matching topics has not changed
+ Changed *bool `protobuf:"varint,5,opt,name=changed,def=1" json:"changed,omitempty"`
+}
+
+// Default values for CommandGetTopicsOfNamespaceResponse fields.
+const (
+ Default_CommandGetTopicsOfNamespaceResponse_Filtered = bool(false)
+ Default_CommandGetTopicsOfNamespaceResponse_Changed = bool(true)
+)
+
+func (x *CommandGetTopicsOfNamespaceResponse) Reset() {
+ *x = CommandGetTopicsOfNamespaceResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[46]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandGetTopicsOfNamespaceResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandGetTopicsOfNamespaceResponse) ProtoMessage() {}
+
+func (x *CommandGetTopicsOfNamespaceResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[46]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandGetTopicsOfNamespaceResponse.ProtoReflect.Descriptor instead.
+func (*CommandGetTopicsOfNamespaceResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{46}
+}
+
+func (x *CommandGetTopicsOfNamespaceResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandGetTopicsOfNamespaceResponse) GetTopics() []string {
+ if x != nil {
+ return x.Topics
+ }
+ return nil
+}
+
+func (x *CommandGetTopicsOfNamespaceResponse) GetFiltered() bool {
+ if x != nil && x.Filtered != nil {
+ return *x.Filtered
+ }
+ return Default_CommandGetTopicsOfNamespaceResponse_Filtered
+}
+
+func (x *CommandGetTopicsOfNamespaceResponse) GetTopicsHash() string {
+ if x != nil && x.TopicsHash != nil {
+ return *x.TopicsHash
+ }
+ return ""
+}
+
+func (x *CommandGetTopicsOfNamespaceResponse) GetChanged() bool {
+ if x != nil && x.Changed != nil {
+ return *x.Changed
+ }
+ return Default_CommandGetTopicsOfNamespaceResponse_Changed
+}
+
+type CommandWatchTopicList struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ WatcherId *uint64 `protobuf:"varint,2,req,name=watcher_id,json=watcherId" json:"watcher_id,omitempty"`
+ Namespace *string `protobuf:"bytes,3,req,name=namespace" json:"namespace,omitempty"`
+ TopicsPattern *string `protobuf:"bytes,4,req,name=topics_pattern,json=topicsPattern" json:"topics_pattern,omitempty"`
+ // Only present when the client reconnects:
+ TopicsHash *string `protobuf:"bytes,5,opt,name=topics_hash,json=topicsHash" json:"topics_hash,omitempty"`
+}
+
+func (x *CommandWatchTopicList) Reset() {
+ *x = CommandWatchTopicList{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[47]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandWatchTopicList) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandWatchTopicList) ProtoMessage() {}
+
+func (x *CommandWatchTopicList) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[47]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandWatchTopicList.ProtoReflect.Descriptor instead.
+func (*CommandWatchTopicList) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{47}
+}
+
+func (x *CommandWatchTopicList) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandWatchTopicList) GetWatcherId() uint64 {
+ if x != nil && x.WatcherId != nil {
+ return *x.WatcherId
+ }
+ return 0
+}
+
+func (x *CommandWatchTopicList) GetNamespace() string {
+ if x != nil && x.Namespace != nil {
+ return *x.Namespace
+ }
+ return ""
+}
+
+func (x *CommandWatchTopicList) GetTopicsPattern() string {
+ if x != nil && x.TopicsPattern != nil {
+ return *x.TopicsPattern
+ }
+ return ""
+}
+
+func (x *CommandWatchTopicList) GetTopicsHash() string {
+ if x != nil && x.TopicsHash != nil {
+ return *x.TopicsHash
+ }
+ return ""
+}
+
+type CommandWatchTopicListSuccess struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ WatcherId *uint64 `protobuf:"varint,2,req,name=watcher_id,json=watcherId" json:"watcher_id,omitempty"`
+ Topic []string `protobuf:"bytes,3,rep,name=topic" json:"topic,omitempty"`
+ TopicsHash *string `protobuf:"bytes,4,req,name=topics_hash,json=topicsHash" json:"topics_hash,omitempty"`
+}
+
+func (x *CommandWatchTopicListSuccess) Reset() {
+ *x = CommandWatchTopicListSuccess{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[48]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandWatchTopicListSuccess) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandWatchTopicListSuccess) ProtoMessage() {}
+
+func (x *CommandWatchTopicListSuccess) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[48]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandWatchTopicListSuccess.ProtoReflect.Descriptor instead.
+func (*CommandWatchTopicListSuccess) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{48}
+}
+
+func (x *CommandWatchTopicListSuccess) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandWatchTopicListSuccess) GetWatcherId() uint64 {
+ if x != nil && x.WatcherId != nil {
+ return *x.WatcherId
+ }
+ return 0
+}
+
+func (x *CommandWatchTopicListSuccess) GetTopic() []string {
+ if x != nil {
+ return x.Topic
+ }
+ return nil
+}
+
+func (x *CommandWatchTopicListSuccess) GetTopicsHash() string {
+ if x != nil && x.TopicsHash != nil {
+ return *x.TopicsHash
+ }
+ return ""
+}
+
+type CommandWatchTopicUpdate struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ WatcherId *uint64 `protobuf:"varint,1,req,name=watcher_id,json=watcherId" json:"watcher_id,omitempty"`
+ NewTopics []string `protobuf:"bytes,2,rep,name=new_topics,json=newTopics" json:"new_topics,omitempty"`
+ DeletedTopics []string `protobuf:"bytes,3,rep,name=deleted_topics,json=deletedTopics" json:"deleted_topics,omitempty"`
+ TopicsHash *string `protobuf:"bytes,4,req,name=topics_hash,json=topicsHash" json:"topics_hash,omitempty"`
+}
+
+func (x *CommandWatchTopicUpdate) Reset() {
+ *x = CommandWatchTopicUpdate{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[49]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandWatchTopicUpdate) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandWatchTopicUpdate) ProtoMessage() {}
+
+func (x *CommandWatchTopicUpdate) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[49]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandWatchTopicUpdate.ProtoReflect.Descriptor instead.
+func (*CommandWatchTopicUpdate) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{49}
+}
+
+func (x *CommandWatchTopicUpdate) GetWatcherId() uint64 {
+ if x != nil && x.WatcherId != nil {
+ return *x.WatcherId
+ }
+ return 0
+}
+
+func (x *CommandWatchTopicUpdate) GetNewTopics() []string {
+ if x != nil {
+ return x.NewTopics
+ }
+ return nil
+}
+
+func (x *CommandWatchTopicUpdate) GetDeletedTopics() []string {
+ if x != nil {
+ return x.DeletedTopics
+ }
+ return nil
+}
+
+func (x *CommandWatchTopicUpdate) GetTopicsHash() string {
+ if x != nil && x.TopicsHash != nil {
+ return *x.TopicsHash
+ }
+ return ""
+}
+
+type CommandWatchTopicListClose struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ WatcherId *uint64 `protobuf:"varint,2,req,name=watcher_id,json=watcherId" json:"watcher_id,omitempty"`
+}
+
+func (x *CommandWatchTopicListClose) Reset() {
+ *x = CommandWatchTopicListClose{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[50]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandWatchTopicListClose) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandWatchTopicListClose) ProtoMessage() {}
+
+func (x *CommandWatchTopicListClose) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[50]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandWatchTopicListClose.ProtoReflect.Descriptor instead.
+func (*CommandWatchTopicListClose) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{50}
+}
+
+func (x *CommandWatchTopicListClose) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandWatchTopicListClose) GetWatcherId() uint64 {
+ if x != nil && x.WatcherId != nil {
+ return *x.WatcherId
+ }
+ return 0
+}
+
+type CommandGetSchema struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Topic *string `protobuf:"bytes,2,req,name=topic" json:"topic,omitempty"`
+ SchemaVersion []byte `protobuf:"bytes,3,opt,name=schema_version,json=schemaVersion" json:"schema_version,omitempty"`
+}
+
+func (x *CommandGetSchema) Reset() {
+ *x = CommandGetSchema{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[51]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandGetSchema) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandGetSchema) ProtoMessage() {}
+
+func (x *CommandGetSchema) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[51]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandGetSchema.ProtoReflect.Descriptor instead.
+func (*CommandGetSchema) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{51}
+}
+
+func (x *CommandGetSchema) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandGetSchema) GetTopic() string {
+ if x != nil && x.Topic != nil {
+ return *x.Topic
+ }
+ return ""
+}
+
+func (x *CommandGetSchema) GetSchemaVersion() []byte {
+ if x != nil {
+ return x.SchemaVersion
+ }
+ return nil
+}
+
+type CommandGetSchemaResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ ErrorCode *ServerError `protobuf:"varint,2,opt,name=error_code,json=errorCode,enum=pulsar.proto.ServerError" json:"error_code,omitempty"`
+ ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage" json:"error_message,omitempty"`
+ Schema *Schema `protobuf:"bytes,4,opt,name=schema" json:"schema,omitempty"`
+ SchemaVersion []byte `protobuf:"bytes,5,opt,name=schema_version,json=schemaVersion" json:"schema_version,omitempty"`
+}
+
+func (x *CommandGetSchemaResponse) Reset() {
+ *x = CommandGetSchemaResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[52]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandGetSchemaResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandGetSchemaResponse) ProtoMessage() {}
+
+func (x *CommandGetSchemaResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[52]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandGetSchemaResponse.ProtoReflect.Descriptor instead.
+func (*CommandGetSchemaResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{52}
+}
+
+func (x *CommandGetSchemaResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandGetSchemaResponse) GetErrorCode() ServerError {
+ if x != nil && x.ErrorCode != nil {
+ return *x.ErrorCode
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandGetSchemaResponse) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
+func (x *CommandGetSchemaResponse) GetSchema() *Schema {
+ if x != nil {
+ return x.Schema
+ }
+ return nil
+}
+
+func (x *CommandGetSchemaResponse) GetSchemaVersion() []byte {
+ if x != nil {
+ return x.SchemaVersion
+ }
+ return nil
+}
+
+type CommandGetOrCreateSchema struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Topic *string `protobuf:"bytes,2,req,name=topic" json:"topic,omitempty"`
+ Schema *Schema `protobuf:"bytes,3,req,name=schema" json:"schema,omitempty"`
+}
+
+func (x *CommandGetOrCreateSchema) Reset() {
+ *x = CommandGetOrCreateSchema{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[53]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandGetOrCreateSchema) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandGetOrCreateSchema) ProtoMessage() {}
+
+func (x *CommandGetOrCreateSchema) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[53]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandGetOrCreateSchema.ProtoReflect.Descriptor instead.
+func (*CommandGetOrCreateSchema) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{53}
+}
+
+func (x *CommandGetOrCreateSchema) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandGetOrCreateSchema) GetTopic() string {
+ if x != nil && x.Topic != nil {
+ return *x.Topic
+ }
+ return ""
+}
+
+func (x *CommandGetOrCreateSchema) GetSchema() *Schema {
+ if x != nil {
+ return x.Schema
+ }
+ return nil
+}
+
+type CommandGetOrCreateSchemaResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ ErrorCode *ServerError `protobuf:"varint,2,opt,name=error_code,json=errorCode,enum=pulsar.proto.ServerError" json:"error_code,omitempty"`
+ ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage" json:"error_message,omitempty"`
+ SchemaVersion []byte `protobuf:"bytes,4,opt,name=schema_version,json=schemaVersion" json:"schema_version,omitempty"`
+}
+
+func (x *CommandGetOrCreateSchemaResponse) Reset() {
+ *x = CommandGetOrCreateSchemaResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[54]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandGetOrCreateSchemaResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandGetOrCreateSchemaResponse) ProtoMessage() {}
+
+func (x *CommandGetOrCreateSchemaResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[54]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandGetOrCreateSchemaResponse.ProtoReflect.Descriptor instead.
+func (*CommandGetOrCreateSchemaResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{54}
+}
+
+func (x *CommandGetOrCreateSchemaResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandGetOrCreateSchemaResponse) GetErrorCode() ServerError {
+ if x != nil && x.ErrorCode != nil {
+ return *x.ErrorCode
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandGetOrCreateSchemaResponse) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
+func (x *CommandGetOrCreateSchemaResponse) GetSchemaVersion() []byte {
+ if x != nil {
+ return x.SchemaVersion
+ }
+ return nil
+}
+
+type CommandTcClientConnectRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TcId *uint64 `protobuf:"varint,2,req,name=tc_id,json=tcId,def=0" json:"tc_id,omitempty"`
+}
+
+// Default values for CommandTcClientConnectRequest fields.
+const (
+ Default_CommandTcClientConnectRequest_TcId = uint64(0)
+)
+
+func (x *CommandTcClientConnectRequest) Reset() {
+ *x = CommandTcClientConnectRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[55]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandTcClientConnectRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandTcClientConnectRequest) ProtoMessage() {}
+
+func (x *CommandTcClientConnectRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[55]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandTcClientConnectRequest.ProtoReflect.Descriptor instead.
+func (*CommandTcClientConnectRequest) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{55}
+}
+
+func (x *CommandTcClientConnectRequest) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandTcClientConnectRequest) GetTcId() uint64 {
+ if x != nil && x.TcId != nil {
+ return *x.TcId
+ }
+ return Default_CommandTcClientConnectRequest_TcId
+}
+
+type CommandTcClientConnectResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ Error *ServerError `protobuf:"varint,2,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
+}
+
+func (x *CommandTcClientConnectResponse) Reset() {
+ *x = CommandTcClientConnectResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[56]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandTcClientConnectResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandTcClientConnectResponse) ProtoMessage() {}
+
+func (x *CommandTcClientConnectResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[56]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandTcClientConnectResponse.ProtoReflect.Descriptor instead.
+func (*CommandTcClientConnectResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{56}
+}
+
+func (x *CommandTcClientConnectResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandTcClientConnectResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandTcClientConnectResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type CommandNewTxn struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnTtlSeconds *uint64 `protobuf:"varint,2,opt,name=txn_ttl_seconds,json=txnTtlSeconds,def=0" json:"txn_ttl_seconds,omitempty"`
+ TcId *uint64 `protobuf:"varint,3,opt,name=tc_id,json=tcId,def=0" json:"tc_id,omitempty"`
+}
+
+// Default values for CommandNewTxn fields.
+const (
+ Default_CommandNewTxn_TxnTtlSeconds = uint64(0)
+ Default_CommandNewTxn_TcId = uint64(0)
+)
+
+func (x *CommandNewTxn) Reset() {
+ *x = CommandNewTxn{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[57]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandNewTxn) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandNewTxn) ProtoMessage() {}
+
+func (x *CommandNewTxn) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[57]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandNewTxn.ProtoReflect.Descriptor instead.
+func (*CommandNewTxn) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{57}
+}
+
+func (x *CommandNewTxn) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandNewTxn) GetTxnTtlSeconds() uint64 {
+ if x != nil && x.TxnTtlSeconds != nil {
+ return *x.TxnTtlSeconds
+ }
+ return Default_CommandNewTxn_TxnTtlSeconds
+}
+
+func (x *CommandNewTxn) GetTcId() uint64 {
+ if x != nil && x.TcId != nil {
+ return *x.TcId
+ }
+ return Default_CommandNewTxn_TcId
+}
+
+type CommandNewTxnResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Error *ServerError `protobuf:"varint,4,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"`
+}
+
+// Default values for CommandNewTxnResponse fields.
+const (
+ Default_CommandNewTxnResponse_TxnidLeastBits = uint64(0)
+ Default_CommandNewTxnResponse_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandNewTxnResponse) Reset() {
+ *x = CommandNewTxnResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[58]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandNewTxnResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandNewTxnResponse) ProtoMessage() {}
+
+func (x *CommandNewTxnResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[58]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandNewTxnResponse.ProtoReflect.Descriptor instead.
+func (*CommandNewTxnResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{58}
+}
+
+func (x *CommandNewTxnResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandNewTxnResponse) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandNewTxnResponse_TxnidLeastBits
+}
+
+func (x *CommandNewTxnResponse) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandNewTxnResponse_TxnidMostBits
+}
+
+func (x *CommandNewTxnResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandNewTxnResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type CommandAddPartitionToTxn struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Partitions []string `protobuf:"bytes,4,rep,name=partitions" json:"partitions,omitempty"`
+}
+
+// Default values for CommandAddPartitionToTxn fields.
+const (
+ Default_CommandAddPartitionToTxn_TxnidLeastBits = uint64(0)
+ Default_CommandAddPartitionToTxn_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandAddPartitionToTxn) Reset() {
+ *x = CommandAddPartitionToTxn{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[59]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandAddPartitionToTxn) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandAddPartitionToTxn) ProtoMessage() {}
+
+func (x *CommandAddPartitionToTxn) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[59]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandAddPartitionToTxn.ProtoReflect.Descriptor instead.
+func (*CommandAddPartitionToTxn) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{59}
+}
+
+func (x *CommandAddPartitionToTxn) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandAddPartitionToTxn) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandAddPartitionToTxn_TxnidLeastBits
+}
+
+func (x *CommandAddPartitionToTxn) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandAddPartitionToTxn_TxnidMostBits
+}
+
+func (x *CommandAddPartitionToTxn) GetPartitions() []string {
+ if x != nil {
+ return x.Partitions
+ }
+ return nil
+}
+
+type CommandAddPartitionToTxnResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Error *ServerError `protobuf:"varint,4,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"`
+}
+
+// Default values for CommandAddPartitionToTxnResponse fields.
+const (
+ Default_CommandAddPartitionToTxnResponse_TxnidLeastBits = uint64(0)
+ Default_CommandAddPartitionToTxnResponse_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandAddPartitionToTxnResponse) Reset() {
+ *x = CommandAddPartitionToTxnResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[60]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandAddPartitionToTxnResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandAddPartitionToTxnResponse) ProtoMessage() {}
+
+func (x *CommandAddPartitionToTxnResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[60]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandAddPartitionToTxnResponse.ProtoReflect.Descriptor instead.
+func (*CommandAddPartitionToTxnResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{60}
+}
+
+func (x *CommandAddPartitionToTxnResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandAddPartitionToTxnResponse) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandAddPartitionToTxnResponse_TxnidLeastBits
+}
+
+func (x *CommandAddPartitionToTxnResponse) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandAddPartitionToTxnResponse_TxnidMostBits
+}
+
+func (x *CommandAddPartitionToTxnResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandAddPartitionToTxnResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type Subscription struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Topic *string `protobuf:"bytes,1,req,name=topic" json:"topic,omitempty"`
+ Subscription *string `protobuf:"bytes,2,req,name=subscription" json:"subscription,omitempty"`
+}
+
+func (x *Subscription) Reset() {
+ *x = Subscription{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[61]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Subscription) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Subscription) ProtoMessage() {}
+
+func (x *Subscription) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[61]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Subscription.ProtoReflect.Descriptor instead.
+func (*Subscription) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{61}
+}
+
+func (x *Subscription) GetTopic() string {
+ if x != nil && x.Topic != nil {
+ return *x.Topic
+ }
+ return ""
+}
+
+func (x *Subscription) GetSubscription() string {
+ if x != nil && x.Subscription != nil {
+ return *x.Subscription
+ }
+ return ""
+}
+
+type CommandAddSubscriptionToTxn struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Subscription []*Subscription `protobuf:"bytes,4,rep,name=subscription" json:"subscription,omitempty"`
+}
+
+// Default values for CommandAddSubscriptionToTxn fields.
+const (
+ Default_CommandAddSubscriptionToTxn_TxnidLeastBits = uint64(0)
+ Default_CommandAddSubscriptionToTxn_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandAddSubscriptionToTxn) Reset() {
+ *x = CommandAddSubscriptionToTxn{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[62]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandAddSubscriptionToTxn) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandAddSubscriptionToTxn) ProtoMessage() {}
+
+func (x *CommandAddSubscriptionToTxn) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[62]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandAddSubscriptionToTxn.ProtoReflect.Descriptor instead.
+func (*CommandAddSubscriptionToTxn) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{62}
+}
+
+func (x *CommandAddSubscriptionToTxn) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandAddSubscriptionToTxn) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandAddSubscriptionToTxn_TxnidLeastBits
+}
+
+func (x *CommandAddSubscriptionToTxn) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandAddSubscriptionToTxn_TxnidMostBits
+}
+
+func (x *CommandAddSubscriptionToTxn) GetSubscription() []*Subscription {
+ if x != nil {
+ return x.Subscription
+ }
+ return nil
+}
+
+type CommandAddSubscriptionToTxnResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Error *ServerError `protobuf:"varint,4,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"`
+}
+
+// Default values for CommandAddSubscriptionToTxnResponse fields.
+const (
+ Default_CommandAddSubscriptionToTxnResponse_TxnidLeastBits = uint64(0)
+ Default_CommandAddSubscriptionToTxnResponse_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandAddSubscriptionToTxnResponse) Reset() {
+ *x = CommandAddSubscriptionToTxnResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[63]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandAddSubscriptionToTxnResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandAddSubscriptionToTxnResponse) ProtoMessage() {}
+
+func (x *CommandAddSubscriptionToTxnResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[63]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandAddSubscriptionToTxnResponse.ProtoReflect.Descriptor instead.
+func (*CommandAddSubscriptionToTxnResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{63}
+}
+
+func (x *CommandAddSubscriptionToTxnResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandAddSubscriptionToTxnResponse) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandAddSubscriptionToTxnResponse_TxnidLeastBits
+}
+
+func (x *CommandAddSubscriptionToTxnResponse) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandAddSubscriptionToTxnResponse_TxnidMostBits
+}
+
+func (x *CommandAddSubscriptionToTxnResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandAddSubscriptionToTxnResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type CommandEndTxn struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ TxnAction *TxnAction `protobuf:"varint,4,opt,name=txn_action,json=txnAction,enum=pulsar.proto.TxnAction" json:"txn_action,omitempty"`
+}
+
+// Default values for CommandEndTxn fields.
+const (
+ Default_CommandEndTxn_TxnidLeastBits = uint64(0)
+ Default_CommandEndTxn_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandEndTxn) Reset() {
+ *x = CommandEndTxn{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[64]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandEndTxn) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandEndTxn) ProtoMessage() {}
+
+func (x *CommandEndTxn) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[64]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandEndTxn.ProtoReflect.Descriptor instead.
+func (*CommandEndTxn) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{64}
+}
+
+func (x *CommandEndTxn) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandEndTxn) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandEndTxn_TxnidLeastBits
+}
+
+func (x *CommandEndTxn) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandEndTxn_TxnidMostBits
+}
+
+func (x *CommandEndTxn) GetTxnAction() TxnAction {
+ if x != nil && x.TxnAction != nil {
+ return *x.TxnAction
+ }
+ return TxnAction_COMMIT
+}
+
+type CommandEndTxnResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Error *ServerError `protobuf:"varint,4,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"`
+}
+
+// Default values for CommandEndTxnResponse fields.
+const (
+ Default_CommandEndTxnResponse_TxnidLeastBits = uint64(0)
+ Default_CommandEndTxnResponse_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandEndTxnResponse) Reset() {
+ *x = CommandEndTxnResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[65]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandEndTxnResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandEndTxnResponse) ProtoMessage() {}
+
+func (x *CommandEndTxnResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[65]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandEndTxnResponse.ProtoReflect.Descriptor instead.
+func (*CommandEndTxnResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{65}
+}
+
+func (x *CommandEndTxnResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandEndTxnResponse) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandEndTxnResponse_TxnidLeastBits
+}
+
+func (x *CommandEndTxnResponse) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandEndTxnResponse_TxnidMostBits
+}
+
+func (x *CommandEndTxnResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandEndTxnResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type CommandEndTxnOnPartition struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Topic *string `protobuf:"bytes,4,opt,name=topic" json:"topic,omitempty"`
+ TxnAction *TxnAction `protobuf:"varint,5,opt,name=txn_action,json=txnAction,enum=pulsar.proto.TxnAction" json:"txn_action,omitempty"`
+ TxnidLeastBitsOfLowWatermark *uint64 `protobuf:"varint,6,opt,name=txnid_least_bits_of_low_watermark,json=txnidLeastBitsOfLowWatermark" json:"txnid_least_bits_of_low_watermark,omitempty"`
+}
+
+// Default values for CommandEndTxnOnPartition fields.
+const (
+ Default_CommandEndTxnOnPartition_TxnidLeastBits = uint64(0)
+ Default_CommandEndTxnOnPartition_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandEndTxnOnPartition) Reset() {
+ *x = CommandEndTxnOnPartition{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[66]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandEndTxnOnPartition) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandEndTxnOnPartition) ProtoMessage() {}
+
+func (x *CommandEndTxnOnPartition) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[66]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandEndTxnOnPartition.ProtoReflect.Descriptor instead.
+func (*CommandEndTxnOnPartition) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{66}
+}
+
+func (x *CommandEndTxnOnPartition) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandEndTxnOnPartition) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandEndTxnOnPartition_TxnidLeastBits
+}
+
+func (x *CommandEndTxnOnPartition) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandEndTxnOnPartition_TxnidMostBits
+}
+
+func (x *CommandEndTxnOnPartition) GetTopic() string {
+ if x != nil && x.Topic != nil {
+ return *x.Topic
+ }
+ return ""
+}
+
+func (x *CommandEndTxnOnPartition) GetTxnAction() TxnAction {
+ if x != nil && x.TxnAction != nil {
+ return *x.TxnAction
+ }
+ return TxnAction_COMMIT
+}
+
+func (x *CommandEndTxnOnPartition) GetTxnidLeastBitsOfLowWatermark() uint64 {
+ if x != nil && x.TxnidLeastBitsOfLowWatermark != nil {
+ return *x.TxnidLeastBitsOfLowWatermark
+ }
+ return 0
+}
+
+type CommandEndTxnOnPartitionResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Error *ServerError `protobuf:"varint,4,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"`
+}
+
+// Default values for CommandEndTxnOnPartitionResponse fields.
+const (
+ Default_CommandEndTxnOnPartitionResponse_TxnidLeastBits = uint64(0)
+ Default_CommandEndTxnOnPartitionResponse_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandEndTxnOnPartitionResponse) Reset() {
+ *x = CommandEndTxnOnPartitionResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[67]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandEndTxnOnPartitionResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandEndTxnOnPartitionResponse) ProtoMessage() {}
+
+func (x *CommandEndTxnOnPartitionResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[67]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandEndTxnOnPartitionResponse.ProtoReflect.Descriptor instead.
+func (*CommandEndTxnOnPartitionResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{67}
+}
+
+func (x *CommandEndTxnOnPartitionResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandEndTxnOnPartitionResponse) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandEndTxnOnPartitionResponse_TxnidLeastBits
+}
+
+func (x *CommandEndTxnOnPartitionResponse) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandEndTxnOnPartitionResponse_TxnidMostBits
+}
+
+func (x *CommandEndTxnOnPartitionResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandEndTxnOnPartitionResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type CommandEndTxnOnSubscription struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Subscription *Subscription `protobuf:"bytes,4,opt,name=subscription" json:"subscription,omitempty"`
+ TxnAction *TxnAction `protobuf:"varint,5,opt,name=txn_action,json=txnAction,enum=pulsar.proto.TxnAction" json:"txn_action,omitempty"`
+ TxnidLeastBitsOfLowWatermark *uint64 `protobuf:"varint,6,opt,name=txnid_least_bits_of_low_watermark,json=txnidLeastBitsOfLowWatermark" json:"txnid_least_bits_of_low_watermark,omitempty"`
+}
+
+// Default values for CommandEndTxnOnSubscription fields.
+const (
+ Default_CommandEndTxnOnSubscription_TxnidLeastBits = uint64(0)
+ Default_CommandEndTxnOnSubscription_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandEndTxnOnSubscription) Reset() {
+ *x = CommandEndTxnOnSubscription{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[68]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandEndTxnOnSubscription) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandEndTxnOnSubscription) ProtoMessage() {}
+
+func (x *CommandEndTxnOnSubscription) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[68]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandEndTxnOnSubscription.ProtoReflect.Descriptor instead.
+func (*CommandEndTxnOnSubscription) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{68}
+}
+
+func (x *CommandEndTxnOnSubscription) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandEndTxnOnSubscription) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandEndTxnOnSubscription_TxnidLeastBits
+}
+
+func (x *CommandEndTxnOnSubscription) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandEndTxnOnSubscription_TxnidMostBits
+}
+
+func (x *CommandEndTxnOnSubscription) GetSubscription() *Subscription {
+ if x != nil {
+ return x.Subscription
+ }
+ return nil
+}
+
+func (x *CommandEndTxnOnSubscription) GetTxnAction() TxnAction {
+ if x != nil && x.TxnAction != nil {
+ return *x.TxnAction
+ }
+ return TxnAction_COMMIT
+}
+
+func (x *CommandEndTxnOnSubscription) GetTxnidLeastBitsOfLowWatermark() uint64 {
+ if x != nil && x.TxnidLeastBitsOfLowWatermark != nil {
+ return *x.TxnidLeastBitsOfLowWatermark
+ }
+ return 0
+}
+
+type CommandEndTxnOnSubscriptionResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RequestId *uint64 `protobuf:"varint,1,req,name=request_id,json=requestId" json:"request_id,omitempty"`
+ TxnidLeastBits *uint64 `protobuf:"varint,2,opt,name=txnid_least_bits,json=txnidLeastBits,def=0" json:"txnid_least_bits,omitempty"`
+ TxnidMostBits *uint64 `protobuf:"varint,3,opt,name=txnid_most_bits,json=txnidMostBits,def=0" json:"txnid_most_bits,omitempty"`
+ Error *ServerError `protobuf:"varint,4,opt,name=error,enum=pulsar.proto.ServerError" json:"error,omitempty"`
+ Message *string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"`
+}
+
+// Default values for CommandEndTxnOnSubscriptionResponse fields.
+const (
+ Default_CommandEndTxnOnSubscriptionResponse_TxnidLeastBits = uint64(0)
+ Default_CommandEndTxnOnSubscriptionResponse_TxnidMostBits = uint64(0)
+)
+
+func (x *CommandEndTxnOnSubscriptionResponse) Reset() {
+ *x = CommandEndTxnOnSubscriptionResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[69]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CommandEndTxnOnSubscriptionResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CommandEndTxnOnSubscriptionResponse) ProtoMessage() {}
+
+func (x *CommandEndTxnOnSubscriptionResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[69]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CommandEndTxnOnSubscriptionResponse.ProtoReflect.Descriptor instead.
+func (*CommandEndTxnOnSubscriptionResponse) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{69}
+}
+
+func (x *CommandEndTxnOnSubscriptionResponse) GetRequestId() uint64 {
+ if x != nil && x.RequestId != nil {
+ return *x.RequestId
+ }
+ return 0
+}
+
+func (x *CommandEndTxnOnSubscriptionResponse) GetTxnidLeastBits() uint64 {
+ if x != nil && x.TxnidLeastBits != nil {
+ return *x.TxnidLeastBits
+ }
+ return Default_CommandEndTxnOnSubscriptionResponse_TxnidLeastBits
+}
+
+func (x *CommandEndTxnOnSubscriptionResponse) GetTxnidMostBits() uint64 {
+ if x != nil && x.TxnidMostBits != nil {
+ return *x.TxnidMostBits
+ }
+ return Default_CommandEndTxnOnSubscriptionResponse_TxnidMostBits
+}
+
+func (x *CommandEndTxnOnSubscriptionResponse) GetError() ServerError {
+ if x != nil && x.Error != nil {
+ return *x.Error
+ }
+ return ServerError_UnknownError
+}
+
+func (x *CommandEndTxnOnSubscriptionResponse) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+type BaseCommand struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Type *BaseCommand_Type `protobuf:"varint,1,req,name=type,enum=pulsar.proto.BaseCommand_Type" json:"type,omitempty"`
+ Connect *CommandConnect `protobuf:"bytes,2,opt,name=connect" json:"connect,omitempty"`
+ Connected *CommandConnected `protobuf:"bytes,3,opt,name=connected" json:"connected,omitempty"`
+ Subscribe *CommandSubscribe `protobuf:"bytes,4,opt,name=subscribe" json:"subscribe,omitempty"`
+ Producer *CommandProducer `protobuf:"bytes,5,opt,name=producer" json:"producer,omitempty"`
+ Send *CommandSend `protobuf:"bytes,6,opt,name=send" json:"send,omitempty"`
+ SendReceipt *CommandSendReceipt `protobuf:"bytes,7,opt,name=send_receipt,json=sendReceipt" json:"send_receipt,omitempty"`
+ SendError *CommandSendError `protobuf:"bytes,8,opt,name=send_error,json=sendError" json:"send_error,omitempty"`
+ Message *CommandMessage `protobuf:"bytes,9,opt,name=message" json:"message,omitempty"`
+ Ack *CommandAck `protobuf:"bytes,10,opt,name=ack" json:"ack,omitempty"`
+ Flow *CommandFlow `protobuf:"bytes,11,opt,name=flow" json:"flow,omitempty"`
+ Unsubscribe *CommandUnsubscribe `protobuf:"bytes,12,opt,name=unsubscribe" json:"unsubscribe,omitempty"`
+ Success *CommandSuccess `protobuf:"bytes,13,opt,name=success" json:"success,omitempty"`
+ Error *CommandError `protobuf:"bytes,14,opt,name=error" json:"error,omitempty"`
+ CloseProducer *CommandCloseProducer `protobuf:"bytes,15,opt,name=close_producer,json=closeProducer" json:"close_producer,omitempty"`
+ CloseConsumer *CommandCloseConsumer `protobuf:"bytes,16,opt,name=close_consumer,json=closeConsumer" json:"close_consumer,omitempty"`
+ ProducerSuccess *CommandProducerSuccess `protobuf:"bytes,17,opt,name=producer_success,json=producerSuccess" json:"producer_success,omitempty"`
+ Ping *CommandPing `protobuf:"bytes,18,opt,name=ping" json:"ping,omitempty"`
+ Pong *CommandPong `protobuf:"bytes,19,opt,name=pong" json:"pong,omitempty"`
+ RedeliverUnacknowledgedMessages *CommandRedeliverUnacknowledgedMessages `protobuf:"bytes,20,opt,name=redeliverUnacknowledgedMessages" json:"redeliverUnacknowledgedMessages,omitempty"`
+ PartitionMetadata *CommandPartitionedTopicMetadata `protobuf:"bytes,21,opt,name=partitionMetadata" json:"partitionMetadata,omitempty"`
+ PartitionMetadataResponse *CommandPartitionedTopicMetadataResponse `protobuf:"bytes,22,opt,name=partitionMetadataResponse" json:"partitionMetadataResponse,omitempty"`
+ LookupTopic *CommandLookupTopic `protobuf:"bytes,23,opt,name=lookupTopic" json:"lookupTopic,omitempty"`
+ LookupTopicResponse *CommandLookupTopicResponse `protobuf:"bytes,24,opt,name=lookupTopicResponse" json:"lookupTopicResponse,omitempty"`
+ ConsumerStats *CommandConsumerStats `protobuf:"bytes,25,opt,name=consumerStats" json:"consumerStats,omitempty"`
+ ConsumerStatsResponse *CommandConsumerStatsResponse `protobuf:"bytes,26,opt,name=consumerStatsResponse" json:"consumerStatsResponse,omitempty"`
+ ReachedEndOfTopic *CommandReachedEndOfTopic `protobuf:"bytes,27,opt,name=reachedEndOfTopic" json:"reachedEndOfTopic,omitempty"`
+ Seek *CommandSeek `protobuf:"bytes,28,opt,name=seek" json:"seek,omitempty"`
+ GetLastMessageId *CommandGetLastMessageId `protobuf:"bytes,29,opt,name=getLastMessageId" json:"getLastMessageId,omitempty"`
+ GetLastMessageIdResponse *CommandGetLastMessageIdResponse `protobuf:"bytes,30,opt,name=getLastMessageIdResponse" json:"getLastMessageIdResponse,omitempty"`
+ ActiveConsumerChange *CommandActiveConsumerChange `protobuf:"bytes,31,opt,name=active_consumer_change,json=activeConsumerChange" json:"active_consumer_change,omitempty"`
+ GetTopicsOfNamespace *CommandGetTopicsOfNamespace `protobuf:"bytes,32,opt,name=getTopicsOfNamespace" json:"getTopicsOfNamespace,omitempty"`
+ GetTopicsOfNamespaceResponse *CommandGetTopicsOfNamespaceResponse `protobuf:"bytes,33,opt,name=getTopicsOfNamespaceResponse" json:"getTopicsOfNamespaceResponse,omitempty"`
+ GetSchema *CommandGetSchema `protobuf:"bytes,34,opt,name=getSchema" json:"getSchema,omitempty"`
+ GetSchemaResponse *CommandGetSchemaResponse `protobuf:"bytes,35,opt,name=getSchemaResponse" json:"getSchemaResponse,omitempty"`
+ AuthChallenge *CommandAuthChallenge `protobuf:"bytes,36,opt,name=authChallenge" json:"authChallenge,omitempty"`
+ AuthResponse *CommandAuthResponse `protobuf:"bytes,37,opt,name=authResponse" json:"authResponse,omitempty"`
+ AckResponse *CommandAckResponse `protobuf:"bytes,38,opt,name=ackResponse" json:"ackResponse,omitempty"`
+ GetOrCreateSchema *CommandGetOrCreateSchema `protobuf:"bytes,39,opt,name=getOrCreateSchema" json:"getOrCreateSchema,omitempty"`
+ GetOrCreateSchemaResponse *CommandGetOrCreateSchemaResponse `protobuf:"bytes,40,opt,name=getOrCreateSchemaResponse" json:"getOrCreateSchemaResponse,omitempty"`
+ // transaction related
+ NewTxn *CommandNewTxn `protobuf:"bytes,50,opt,name=newTxn" json:"newTxn,omitempty"`
+ NewTxnResponse *CommandNewTxnResponse `protobuf:"bytes,51,opt,name=newTxnResponse" json:"newTxnResponse,omitempty"`
+ AddPartitionToTxn *CommandAddPartitionToTxn `protobuf:"bytes,52,opt,name=addPartitionToTxn" json:"addPartitionToTxn,omitempty"`
+ AddPartitionToTxnResponse *CommandAddPartitionToTxnResponse `protobuf:"bytes,53,opt,name=addPartitionToTxnResponse" json:"addPartitionToTxnResponse,omitempty"`
+ AddSubscriptionToTxn *CommandAddSubscriptionToTxn `protobuf:"bytes,54,opt,name=addSubscriptionToTxn" json:"addSubscriptionToTxn,omitempty"`
+ AddSubscriptionToTxnResponse *CommandAddSubscriptionToTxnResponse `protobuf:"bytes,55,opt,name=addSubscriptionToTxnResponse" json:"addSubscriptionToTxnResponse,omitempty"`
+ EndTxn *CommandEndTxn `protobuf:"bytes,56,opt,name=endTxn" json:"endTxn,omitempty"`
+ EndTxnResponse *CommandEndTxnResponse `protobuf:"bytes,57,opt,name=endTxnResponse" json:"endTxnResponse,omitempty"`
+ EndTxnOnPartition *CommandEndTxnOnPartition `protobuf:"bytes,58,opt,name=endTxnOnPartition" json:"endTxnOnPartition,omitempty"`
+ EndTxnOnPartitionResponse *CommandEndTxnOnPartitionResponse `protobuf:"bytes,59,opt,name=endTxnOnPartitionResponse" json:"endTxnOnPartitionResponse,omitempty"`
+ EndTxnOnSubscription *CommandEndTxnOnSubscription `protobuf:"bytes,60,opt,name=endTxnOnSubscription" json:"endTxnOnSubscription,omitempty"`
+ EndTxnOnSubscriptionResponse *CommandEndTxnOnSubscriptionResponse `protobuf:"bytes,61,opt,name=endTxnOnSubscriptionResponse" json:"endTxnOnSubscriptionResponse,omitempty"`
+ TcClientConnectRequest *CommandTcClientConnectRequest `protobuf:"bytes,62,opt,name=tcClientConnectRequest" json:"tcClientConnectRequest,omitempty"`
+ TcClientConnectResponse *CommandTcClientConnectResponse `protobuf:"bytes,63,opt,name=tcClientConnectResponse" json:"tcClientConnectResponse,omitempty"`
+ WatchTopicList *CommandWatchTopicList `protobuf:"bytes,64,opt,name=watchTopicList" json:"watchTopicList,omitempty"`
+ WatchTopicListSuccess *CommandWatchTopicListSuccess `protobuf:"bytes,65,opt,name=watchTopicListSuccess" json:"watchTopicListSuccess,omitempty"`
+ WatchTopicUpdate *CommandWatchTopicUpdate `protobuf:"bytes,66,opt,name=watchTopicUpdate" json:"watchTopicUpdate,omitempty"`
+ WatchTopicListClose *CommandWatchTopicListClose `protobuf:"bytes,67,opt,name=watchTopicListClose" json:"watchTopicListClose,omitempty"`
+}
+
+func (x *BaseCommand) Reset() {
+ *x = BaseCommand{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_PulsarApi_proto_msgTypes[70]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BaseCommand) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BaseCommand) ProtoMessage() {}
+
+func (x *BaseCommand) ProtoReflect() protoreflect.Message {
+ mi := &file_PulsarApi_proto_msgTypes[70]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BaseCommand.ProtoReflect.Descriptor instead.
+func (*BaseCommand) Descriptor() ([]byte, []int) {
+ return file_PulsarApi_proto_rawDescGZIP(), []int{70}
+}
+
+func (x *BaseCommand) GetType() BaseCommand_Type {
+ if x != nil && x.Type != nil {
+ return *x.Type
+ }
+ return BaseCommand_CONNECT
+}
+
+func (x *BaseCommand) GetConnect() *CommandConnect {
+ if x != nil {
+ return x.Connect
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetConnected() *CommandConnected {
+ if x != nil {
+ return x.Connected
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetSubscribe() *CommandSubscribe {
+ if x != nil {
+ return x.Subscribe
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetProducer() *CommandProducer {
+ if x != nil {
+ return x.Producer
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetSend() *CommandSend {
+ if x != nil {
+ return x.Send
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetSendReceipt() *CommandSendReceipt {
+ if x != nil {
+ return x.SendReceipt
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetSendError() *CommandSendError {
+ if x != nil {
+ return x.SendError
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetMessage() *CommandMessage {
+ if x != nil {
+ return x.Message
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetAck() *CommandAck {
+ if x != nil {
+ return x.Ack
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetFlow() *CommandFlow {
+ if x != nil {
+ return x.Flow
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetUnsubscribe() *CommandUnsubscribe {
+ if x != nil {
+ return x.Unsubscribe
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetSuccess() *CommandSuccess {
+ if x != nil {
+ return x.Success
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetError() *CommandError {
+ if x != nil {
+ return x.Error
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetCloseProducer() *CommandCloseProducer {
+ if x != nil {
+ return x.CloseProducer
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetCloseConsumer() *CommandCloseConsumer {
+ if x != nil {
+ return x.CloseConsumer
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetProducerSuccess() *CommandProducerSuccess {
+ if x != nil {
+ return x.ProducerSuccess
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetPing() *CommandPing {
+ if x != nil {
+ return x.Ping
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetPong() *CommandPong {
+ if x != nil {
+ return x.Pong
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetRedeliverUnacknowledgedMessages() *CommandRedeliverUnacknowledgedMessages {
+ if x != nil {
+ return x.RedeliverUnacknowledgedMessages
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetPartitionMetadata() *CommandPartitionedTopicMetadata {
+ if x != nil {
+ return x.PartitionMetadata
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetPartitionMetadataResponse() *CommandPartitionedTopicMetadataResponse {
+ if x != nil {
+ return x.PartitionMetadataResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetLookupTopic() *CommandLookupTopic {
+ if x != nil {
+ return x.LookupTopic
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetLookupTopicResponse() *CommandLookupTopicResponse {
+ if x != nil {
+ return x.LookupTopicResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetConsumerStats() *CommandConsumerStats {
+ if x != nil {
+ return x.ConsumerStats
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetConsumerStatsResponse() *CommandConsumerStatsResponse {
+ if x != nil {
+ return x.ConsumerStatsResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetReachedEndOfTopic() *CommandReachedEndOfTopic {
+ if x != nil {
+ return x.ReachedEndOfTopic
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetSeek() *CommandSeek {
+ if x != nil {
+ return x.Seek
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetGetLastMessageId() *CommandGetLastMessageId {
+ if x != nil {
+ return x.GetLastMessageId
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetGetLastMessageIdResponse() *CommandGetLastMessageIdResponse {
+ if x != nil {
+ return x.GetLastMessageIdResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetActiveConsumerChange() *CommandActiveConsumerChange {
+ if x != nil {
+ return x.ActiveConsumerChange
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetGetTopicsOfNamespace() *CommandGetTopicsOfNamespace {
+ if x != nil {
+ return x.GetTopicsOfNamespace
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetGetTopicsOfNamespaceResponse() *CommandGetTopicsOfNamespaceResponse {
+ if x != nil {
+ return x.GetTopicsOfNamespaceResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetGetSchema() *CommandGetSchema {
+ if x != nil {
+ return x.GetSchema
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetGetSchemaResponse() *CommandGetSchemaResponse {
+ if x != nil {
+ return x.GetSchemaResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetAuthChallenge() *CommandAuthChallenge {
+ if x != nil {
+ return x.AuthChallenge
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetAuthResponse() *CommandAuthResponse {
+ if x != nil {
+ return x.AuthResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetAckResponse() *CommandAckResponse {
+ if x != nil {
+ return x.AckResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetGetOrCreateSchema() *CommandGetOrCreateSchema {
+ if x != nil {
+ return x.GetOrCreateSchema
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetGetOrCreateSchemaResponse() *CommandGetOrCreateSchemaResponse {
+ if x != nil {
+ return x.GetOrCreateSchemaResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetNewTxn() *CommandNewTxn {
+ if x != nil {
+ return x.NewTxn
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetNewTxnResponse() *CommandNewTxnResponse {
+ if x != nil {
+ return x.NewTxnResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetAddPartitionToTxn() *CommandAddPartitionToTxn {
+ if x != nil {
+ return x.AddPartitionToTxn
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetAddPartitionToTxnResponse() *CommandAddPartitionToTxnResponse {
+ if x != nil {
+ return x.AddPartitionToTxnResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetAddSubscriptionToTxn() *CommandAddSubscriptionToTxn {
+ if x != nil {
+ return x.AddSubscriptionToTxn
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetAddSubscriptionToTxnResponse() *CommandAddSubscriptionToTxnResponse {
+ if x != nil {
+ return x.AddSubscriptionToTxnResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetEndTxn() *CommandEndTxn {
+ if x != nil {
+ return x.EndTxn
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetEndTxnResponse() *CommandEndTxnResponse {
+ if x != nil {
+ return x.EndTxnResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetEndTxnOnPartition() *CommandEndTxnOnPartition {
+ if x != nil {
+ return x.EndTxnOnPartition
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetEndTxnOnPartitionResponse() *CommandEndTxnOnPartitionResponse {
+ if x != nil {
+ return x.EndTxnOnPartitionResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetEndTxnOnSubscription() *CommandEndTxnOnSubscription {
+ if x != nil {
+ return x.EndTxnOnSubscription
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetEndTxnOnSubscriptionResponse() *CommandEndTxnOnSubscriptionResponse {
+ if x != nil {
+ return x.EndTxnOnSubscriptionResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetTcClientConnectRequest() *CommandTcClientConnectRequest {
+ if x != nil {
+ return x.TcClientConnectRequest
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetTcClientConnectResponse() *CommandTcClientConnectResponse {
+ if x != nil {
+ return x.TcClientConnectResponse
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetWatchTopicList() *CommandWatchTopicList {
+ if x != nil {
+ return x.WatchTopicList
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetWatchTopicListSuccess() *CommandWatchTopicListSuccess {
+ if x != nil {
+ return x.WatchTopicListSuccess
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetWatchTopicUpdate() *CommandWatchTopicUpdate {
+ if x != nil {
+ return x.WatchTopicUpdate
+ }
+ return nil
+}
+
+func (x *BaseCommand) GetWatchTopicListClose() *CommandWatchTopicListClose {
+ if x != nil {
+ return x.WatchTopicListClose
+ }
+ return nil
+}
+
+var File_PulsarApi_proto protoreflect.FileDescriptor
+
+var file_PulsarApi_proto_rawDesc = []byte{
+ 0x0a, 0x0f, 0x50, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x41, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x0c, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+ 0xb4, 0x03, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20,
+ 0x02, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12,
+ 0x2d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x02, 0x28, 0x0e, 0x32, 0x19, 0x2e,
+ 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x63, 0x68,
+ 0x65, 0x6d, 0x61, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x36,
+ 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70,
+ 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x8d, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
+ 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x74, 0x72,
+ 0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4a, 0x73, 0x6f, 0x6e, 0x10, 0x02, 0x12,
+ 0x0c, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x10, 0x03, 0x12, 0x08, 0x0a,
+ 0x04, 0x41, 0x76, 0x72, 0x6f, 0x10, 0x04, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6c, 0x10,
+ 0x05, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x6e, 0x74, 0x38, 0x10, 0x06, 0x12, 0x09, 0x0a, 0x05, 0x49,
+ 0x6e, 0x74, 0x31, 0x36, 0x10, 0x07, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x10,
+ 0x08, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x10, 0x09, 0x12, 0x09, 0x0a, 0x05,
+ 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x10, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x6f, 0x75, 0x62, 0x6c,
+ 0x65, 0x10, 0x0b, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x65, 0x10, 0x0c, 0x12, 0x08, 0x0a,
+ 0x04, 0x54, 0x69, 0x6d, 0x65, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73,
+ 0x74, 0x61, 0x6d, 0x70, 0x10, 0x0e, 0x12, 0x0c, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x10, 0x0f, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x10,
+ 0x10, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x65, 0x10, 0x11,
+ 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x10, 0x12, 0x12,
+ 0x11, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65,
+ 0x10, 0x13, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x4e, 0x61,
+ 0x74, 0x69, 0x76, 0x65, 0x10, 0x14, 0x22, 0x96, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x49, 0x64, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x65, 0x64, 0x67,
+ 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x08, 0x6c, 0x65, 0x64, 0x67,
+ 0x65, 0x72, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x18,
+ 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x20,
+ 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x05, 0x3a, 0x02, 0x2d, 0x31, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x12, 0x23, 0x0a, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x02, 0x2d, 0x31, 0x52, 0x0a, 0x62, 0x61, 0x74, 0x63, 0x68,
+ 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74,
+ 0x18, 0x05, 0x20, 0x03, 0x28, 0x03, 0x52, 0x06, 0x61, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x12, 0x1d,
+ 0x0a, 0x0a, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x05, 0x52, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x50, 0x0a,
+ 0x16, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x6d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+ 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x13, 0x66, 0x69, 0x72, 0x73,
+ 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22,
+ 0x32, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b,
+ 0x65, 0x79, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x22, 0x36, 0x0a, 0x0c, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x6e, 0x67, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09,
+ 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
+ 0x20, 0x02, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x49,
+ 0x6e, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x18, 0x01, 0x20, 0x02, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a,
+ 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22,
+ 0x6c, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79,
+ 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x03,
+ 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x02,
+ 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x6d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xd1, 0x09,
+ 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+ 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63,
+ 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e,
+ 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x73, 0x65, 0x71,
+ 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69,
+ 0x73, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0b, 0x70,
+ 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x72,
+ 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
+ 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65,
+ 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69,
+ 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64,
+ 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70,
+ 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x23, 0x0a, 0x0d, 0x70,
+ 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79,
+ 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x6f,
+ 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,
+ 0x65, 0x54, 0x6f, 0x12, 0x45, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69,
+ 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73,
+ 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x52, 0x0b, 0x63,
+ 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x11, 0x75, 0x6e,
+ 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
+ 0x09, 0x20, 0x01, 0x28, 0x0d, 0x3a, 0x01, 0x30, 0x52, 0x10, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70,
+ 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x34, 0x0a, 0x15, 0x6e, 0x75,
+ 0x6d, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x61,
+ 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x01, 0x31, 0x52, 0x12, 0x6e, 0x75,
+ 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x49, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68,
+ 0x12, 0x20, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0c,
+ 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69,
+ 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x0f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x0e, 0x65, 0x6e, 0x63, 0x72, 0x79,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x6e, 0x63,
+ 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x18, 0x0e, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6c,
+ 0x67, 0x6f, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x65, 0x6e,
+ 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x25, 0x0a,
+ 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
+ 0x10, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72,
+ 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x19, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x36, 0x34, 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65,
+ 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x16,
+ 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x42, 0x36, 0x34, 0x45,
+ 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x69,
+ 0x6e, 0x67, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x65, 0x6c,
+ 0x69, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x13, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x0d, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x41, 0x74, 0x54, 0x69, 0x6d,
+ 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65,
+ 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x79,
+ 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73,
+ 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x78,
+ 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f,
+ 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18,
+ 0x17, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74,
+ 0x42, 0x69, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x13, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x5f,
+ 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x18, 0x20, 0x01, 0x28,
+ 0x04, 0x3a, 0x01, 0x30, 0x52, 0x11, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x53, 0x65, 0x71,
+ 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0a, 0x6e, 0x75, 0x6c, 0x6c, 0x5f,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c,
+ 0x73, 0x65, 0x52, 0x09, 0x6e, 0x75, 0x6c, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a,
+ 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69,
+ 0x64, 0x12, 0x2d, 0x0a, 0x13, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x5f,
+ 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10,
+ 0x6e, 0x75, 0x6d, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x4d, 0x73, 0x67,
+ 0x12, 0x2f, 0x0a, 0x14, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f,
+ 0x6d, 0x73, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11,
+ 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x73, 0x67, 0x53, 0x69, 0x7a,
+ 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x1d, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x12,
+ 0x6e, 0x75, 0x6c, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b,
+ 0x65, 0x79, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+ 0x10, 0x6e, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65,
+ 0x79, 0x22, 0xc6, 0x03, 0x0a, 0x15, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x36, 0x0a, 0x0a, 0x70,
+ 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x16, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b,
+ 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74,
+ 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x74,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6c,
+ 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x02, 0x28, 0x05, 0x52, 0x0b,
+ 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2a, 0x0a, 0x0d, 0x63,
+ 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x70, 0x61,
+ 0x63, 0x74, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74,
+ 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x09,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x19, 0x70, 0x61, 0x72,
+ 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x36, 0x34, 0x5f, 0x65,
+ 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
+ 0x6c, 0x73, 0x65, 0x52, 0x16, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65,
+ 0x79, 0x42, 0x36, 0x34, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x0b, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x0a, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12,
+ 0x24, 0x0a, 0x0a, 0x6e, 0x75, 0x6c, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20,
+ 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x09, 0x6e, 0x75, 0x6c, 0x6c,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x33, 0x0a, 0x12, 0x6e, 0x75, 0x6c, 0x6c, 0x5f, 0x70, 0x61,
+ 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28,
+ 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x10, 0x6e, 0x75, 0x6c, 0x6c, 0x50, 0x61,
+ 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x22, 0x56, 0x0a, 0x13, 0x42, 0x72,
+ 0x6f, 0x6b, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+ 0x61, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x62, 0x72, 0x6f,
+ 0x6b, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05,
+ 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64,
+ 0x65, 0x78, 0x22, 0xe6, 0x03, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
+ 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x0d, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0b,
+ 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x0a, 0x61, 0x75, 0x74,
+ 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x61, 0x75, 0x74, 0x68, 0x5f,
+ 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4e, 0x61, 0x6d,
+ 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2c,
+ 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69,
+ 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x01, 0x30, 0x52, 0x0f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x13,
+ 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x5f,
+ 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x78, 0x79,
+ 0x54, 0x6f, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x6f,
+ 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
+ 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
+ 0x6c, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x72,
+ 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61,
+ 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
+ 0x41, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x30, 0x0a, 0x14, 0x6f, 0x72, 0x69, 0x67,
+ 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
+ 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
+ 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x3f, 0x0a, 0x0d, 0x66, 0x65,
+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x0c, 0x66,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x97, 0x02, 0x0a, 0x0c,
+ 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x39, 0x0a, 0x15,
+ 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x72, 0x65,
+ 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c,
+ 0x73, 0x65, 0x52, 0x13, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x41, 0x75, 0x74, 0x68,
+ 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x4a, 0x0a, 0x1e, 0x73, 0x75, 0x70, 0x70, 0x6f,
+ 0x72, 0x74, 0x73, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79,
+ 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a,
+ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1b, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73,
+ 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x64,
+ 0x61, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x19, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f,
+ 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x17, 0x73,
+ 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x72,
+ 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x17, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72,
+ 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x5f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
+ 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x15,
+ 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x57, 0x61, 0x74,
+ 0x63, 0x68, 0x65, 0x72, 0x73, 0x22, 0xd2, 0x01, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x02,
+ 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
+ 0x6e, 0x12, 0x2c, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65,
+ 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x01, 0x30, 0x52, 0x0f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
+ 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73,
+ 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x3f, 0x0a, 0x0d, 0x66, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1a, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x0c, 0x66, 0x65,
+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x9e, 0x01, 0x0a, 0x13, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65,
+ 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x08, 0x72, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x44,
+ 0x61, 0x74, 0x61, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a,
+ 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+ 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x01, 0x30, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa1, 0x01, 0x0a, 0x14,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x75, 0x74, 0x68, 0x43, 0x68, 0x61, 0x6c, 0x6c,
+ 0x65, 0x6e, 0x67, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76,
+ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x09, 0x63,
+ 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16,
+ 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75,
+ 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67,
+ 0x65, 0x12, 0x2c, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65,
+ 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x3a, 0x01, 0x30, 0x52, 0x0f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22,
+ 0x51, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x10, 0x61,
+ 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f,
+ 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x64, 0x61,
+ 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x44, 0x61,
+ 0x74, 0x61, 0x22, 0xcb, 0x01, 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64,
+ 0x4d, 0x65, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x0d, 0x6b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65,
+ 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x68,
+ 0x61, 0x72, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0d, 0x6b, 0x65, 0x79, 0x53, 0x68, 0x61,
+ 0x72, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x68, 0x61, 0x73, 0x68, 0x52,
+ 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x61,
+ 0x6e, 0x67, 0x65, 0x52, 0x0a, 0x68, 0x61, 0x73, 0x68, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12,
+ 0x3f, 0x0a, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4f, 0x75, 0x74, 0x4f, 0x66, 0x4f, 0x72, 0x64,
+ 0x65, 0x72, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
+ 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4f, 0x75,
+ 0x74, 0x4f, 0x66, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79,
+ 0x22, 0xe3, 0x08, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73,
+ 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01,
+ 0x20, 0x02, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x73,
+ 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28,
+ 0x09, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
+ 0x40, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x02, 0x28, 0x0e,
+ 0x32, 0x26, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
+ 0x2e, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x73, 0x75, 0x62, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64,
+ 0x18, 0x04, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
+ 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64,
+ 0x18, 0x05, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49,
+ 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d,
+ 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69,
+ 0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d,
+ 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1e, 0x0a,
+ 0x07, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04,
+ 0x74, 0x72, 0x75, 0x65, 0x52, 0x07, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x45, 0x0a,
+ 0x10, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69,
+ 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64,
+ 0x44, 0x61, 0x74, 0x61, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08,
+ 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x61, 0x64,
+ 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x0d, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x65, 0x64, 0x12,
+ 0x2c, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x14, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
+ 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x60, 0x0a,
+ 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x75, 0x62,
+ 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x06, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x0f,
+ 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12,
+ 0x40, 0x0a, 0x1c, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x62,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
+ 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65,
+ 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x12, 0x36, 0x0a, 0x14, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63,
+ 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x3a,
+ 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x12, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x54, 0x6f, 0x70, 0x69,
+ 0x63, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4f, 0x0a, 0x23, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x6f, 0x6c, 0x6c, 0x62,
+ 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x63,
+ 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x1f, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x44,
+ 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x12, 0x41, 0x0a, 0x0d, 0x6b, 0x65,
+ 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x11, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0d,
+ 0x6b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x4f, 0x0a,
+ 0x17, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72,
+ 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
+ 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65,
+ 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x16, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x25,
+ 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68,
+ 0x18, 0x13, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
+ 0x45, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x42, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65,
+ 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x10, 0x00, 0x12,
+ 0x0a, 0x0a, 0x06, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x46,
+ 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x4b, 0x65, 0x79,
+ 0x5f, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x10, 0x03, 0x22, 0x2b, 0x0a, 0x0f, 0x49, 0x6e, 0x69,
+ 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06,
+ 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x61, 0x72, 0x6c,
+ 0x69, 0x65, 0x73, 0x74, 0x10, 0x01, 0x22, 0xe5, 0x01, 0x0a, 0x1f, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x6f, 0x70,
+ 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f,
+ 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63,
+ 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02,
+ 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12,
+ 0x2d, 0x0a, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x69, 0x6e,
+ 0x63, 0x69, 0x70, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x72, 0x69,
+ 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x12, 0x2c,
+ 0x0a, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f,
+ 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x69, 0x67,
+ 0x69, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x30, 0x0a, 0x14,
+ 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65,
+ 0x74, 0x68, 0x6f, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6f, 0x72, 0x69, 0x67,
+ 0x69, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0xb8,
+ 0x02, 0x0a, 0x27, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61,
+ 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a,
+ 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x5c, 0x0a, 0x08, 0x72, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x40, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x6f, 0x70,
+ 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x72,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f,
+ 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x22, 0x25, 0x0a, 0x0a, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65,
+ 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a,
+ 0x06, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x01, 0x22, 0xbf, 0x02, 0x0a, 0x12, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70, 0x69, 0x63,
+ 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52,
+ 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
+ 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
+ 0x6c, 0x73, 0x65, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x61, 0x74, 0x69,
+ 0x76, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x70,
+ 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11,
+ 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61,
+ 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75,
+ 0x74, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f,
+ 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12,
+ 0x30, 0x0a, 0x14, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68,
+ 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6f,
+ 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f,
+ 0x64, 0x12, 0x38, 0x0a, 0x18, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x5f,
+ 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x16, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x4c,
+ 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd9, 0x03, 0x0a, 0x1a,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70,
+ 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x62, 0x72,
+ 0x6f, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x72, 0x6c, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76,
+ 0x69, 0x63, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72,
+ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x72, 0x6c, 0x54, 0x6c, 0x73, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x13, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69,
+ 0x63, 0x65, 0x55, 0x72, 0x6c, 0x54, 0x6c, 0x73, 0x12, 0x4f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65, 0x52,
+ 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a,
+ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74,
+ 0x61, 0x74, 0x69, 0x76, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52,
+ 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x12, 0x40, 0x0a, 0x19, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67,
+ 0x68, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x08, 0x20,
+ 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x16, 0x70, 0x72, 0x6f, 0x78,
+ 0x79, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55,
+ 0x72, 0x6c, 0x22, 0x33, 0x0a, 0x0a, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65,
+ 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x00, 0x12, 0x0b,
+ 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46,
+ 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x02, 0x22, 0xd2, 0x04, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x74,
+ 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69,
+ 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x69, 0x64,
+ 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
+ 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64,
+ 0x18, 0x03, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49,
+ 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63,
+ 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70,
+ 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
+ 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x08, 0x6d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e,
+ 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
+ 0x2c, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x14, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
+ 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x17, 0x0a,
+ 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52,
+ 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x43, 0x0a, 0x1b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
+ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75,
+ 0x65, 0x52, 0x18, 0x75, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x50,
+ 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5a, 0x0a, 0x14, 0x70,
+ 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d,
+ 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65,
+ 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x06, 0x53, 0x68, 0x61,
+ 0x72, 0x65, 0x64, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x41, 0x63, 0x63,
+ 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x70, 0x69, 0x63,
+ 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x74, 0x6f,
+ 0x70, 0x69, 0x63, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x26, 0x0a, 0x0b, 0x74, 0x78, 0x6e, 0x5f,
+ 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
+ 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x74, 0x78, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
+ 0x12, 0x3a, 0x0a, 0x19, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x17, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xfd, 0x02, 0x0a,
+ 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x0b,
+ 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28,
+ 0x04, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02,
+ 0x28, 0x04, 0x52, 0x0a, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x24,
+ 0x0a, 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x05, 0x3a, 0x01, 0x31, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65,
+ 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01,
+ 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69, 0x74,
+ 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f,
+ 0x62, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0d, 0x74,
+ 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x13,
+ 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65,
+ 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x11, 0x68, 0x69,
+ 0x67, 0x68, 0x65, 0x73, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12,
+ 0x20, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28,
+ 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x07, 0x69, 0x73, 0x43, 0x68, 0x75, 0x6e,
+ 0x6b, 0x12, 0x1d, 0x0a, 0x06, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28,
+ 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x06, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72,
+ 0x12, 0x3a, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x09,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x44, 0x61, 0x74,
+ 0x61, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0xc5, 0x01, 0x0a,
+ 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x63, 0x65,
+ 0x69, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63,
+ 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65,
+ 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x73, 0x65, 0x71, 0x75, 0x65,
+ 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x49, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49,
+ 0x64, 0x12, 0x31, 0x0a, 0x13, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x71,
+ 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01,
+ 0x30, 0x52, 0x11, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e,
+ 0x63, 0x65, 0x49, 0x64, 0x22, 0x9f, 0x01, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x53, 0x65, 0x6e, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a,
+ 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65,
+ 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52,
+ 0x0a, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x05, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x02, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x02, 0x28, 0x09, 0x52, 0x07, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xdb, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e,
+ 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a,
+ 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x0a, 0x6d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x0b, 0x32, 0x1b,
+ 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x09, 0x6d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x10, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x69,
+ 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
+ 0x3a, 0x01, 0x30, 0x52, 0x0f, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x18,
+ 0x04, 0x20, 0x03, 0x28, 0x03, 0x52, 0x06, 0x61, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x12, 0x25, 0x0a,
+ 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x45,
+ 0x70, 0x6f, 0x63, 0x68, 0x22, 0xeb, 0x04, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x41, 0x63, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d,
+ 0x65, 0x72, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x08, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65,
+ 0x18, 0x02, 0x20, 0x02, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x63, 0x6b,
+ 0x2e, 0x41, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x61, 0x63, 0x6b, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18,
+ 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x44, 0x61,
+ 0x74, 0x61, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x53, 0x0a,
+ 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x63,
+ 0x6b, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f,
+ 0x72, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72,
+ 0x6f, 0x72, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73,
+ 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x6e, 0x67, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2b,
+ 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69,
+ 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e,
+ 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74,
+ 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x07,
+ 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f,
+ 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x29, 0x0a, 0x07, 0x41, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65,
+ 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x10, 0x00,
+ 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x10, 0x01,
+ 0x22, 0x8f, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45,
+ 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65,
+ 0x73, 0x73, 0x65, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x43, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65,
+ 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10,
+ 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68,
+ 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x53, 0x65, 0x72,
+ 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x03, 0x12, 0x13, 0x0a,
+ 0x0f, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72,
+ 0x10, 0x04, 0x22, 0xf7, 0x01, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x63,
+ 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e,
+ 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a,
+ 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78,
+ 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65,
+ 0x61, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64,
+ 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
+ 0x3a, 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69,
+ 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x62, 0x0a, 0x1b,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e,
+ 0x73, 0x75, 0x6d, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63,
+ 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04,
+ 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x09,
+ 0x69, 0x73, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a,
+ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x08, 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65,
+ 0x22, 0x56, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x46, 0x6c, 0x6f, 0x77, 0x12,
+ 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01,
+ 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64,
+ 0x12, 0x26, 0x0a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69,
+ 0x74, 0x73, 0x18, 0x02, 0x20, 0x02, 0x28, 0x0d, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x73, 0x22, 0x54, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x02, 0x28, 0x04, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12,
+ 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
+ 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0xbb,
+ 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x65, 0x6b, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x02, 0x28, 0x04, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12,
+ 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
+ 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x3a,
+ 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52,
+ 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x6d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x3b, 0x0a, 0x18,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x6e,
+ 0x64, 0x4f, 0x66, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73,
+ 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x63,
+ 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x22, 0x56, 0x0a, 0x14, 0x43, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65,
+ 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x69, 0x64,
+ 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
+ 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64,
+ 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49,
+ 0x64, 0x22, 0x56, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6c, 0x6f, 0x73,
+ 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e,
+ 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a,
+ 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0xae, 0x01, 0x0a, 0x26, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x55, 0x6e,
+ 0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
+ 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75,
+ 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x49, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x49, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f,
+ 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e,
+ 0x73, 0x75, 0x6d, 0x65, 0x72, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x5d, 0x0a, 0x0e, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04,
+ 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x06, 0x73,
+ 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d,
+ 0x61, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xff, 0x01, 0x0a, 0x16, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x53, 0x75, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74,
+ 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x03, 0x3a, 0x02, 0x2d, 0x31, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x71, 0x75,
+ 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d,
+ 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x2b,
+ 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79,
+ 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x0d, 0x70, 0x72,
+ 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x79, 0x22, 0x78, 0x0a, 0x0c, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52,
+ 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x02, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45,
+ 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x02, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0d, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x50, 0x69, 0x6e, 0x67, 0x22, 0x0d, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50,
+ 0x6f, 0x6e, 0x67, 0x22, 0x56, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6f,
+ 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52,
+ 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f,
+ 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x02, 0x28, 0x04, 0x52,
+ 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x22, 0x98, 0x05, 0x0a, 0x1c,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04,
+ 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0a, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x73,
+ 0x67, 0x52, 0x61, 0x74, 0x65, 0x4f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a,
+ 0x6d, 0x73, 0x67, 0x52, 0x61, 0x74, 0x65, 0x4f, 0x75, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x6d, 0x73,
+ 0x67, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x70, 0x75, 0x74, 0x4f, 0x75, 0x74, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x6d, 0x73, 0x67, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x70, 0x75, 0x74, 0x4f, 0x75, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x6d, 0x73, 0x67, 0x52, 0x61, 0x74,
+ 0x65, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01,
+ 0x52, 0x10, 0x6d, 0x73, 0x67, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x69, 0x76,
+ 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x4e, 0x61,
+ 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d,
+ 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,
+ 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x10, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69,
+ 0x74, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x75, 0x6e, 0x61,
+ 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x1c,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x4f,
+ 0x6e, 0x55, 0x6e, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x1c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x73, 0x75,
+ 0x6d, 0x65, 0x72, 0x4f, 0x6e, 0x55, 0x6e, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x73,
+ 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x69, 0x6e,
+ 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x6d, 0x73, 0x67, 0x52, 0x61, 0x74,
+ 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e,
+ 0x6d, 0x73, 0x67, 0x52, 0x61, 0x74, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x12, 0x1e,
+ 0x0a, 0x0a, 0x6d, 0x73, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x6c, 0x6f, 0x67, 0x18, 0x0f, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x0a, 0x6d, 0x73, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x6c, 0x6f, 0x67, 0x12, 0x26,
+ 0x0a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x52, 0x61, 0x74, 0x65,
+ 0x18, 0x10, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41,
+ 0x63, 0x6b, 0x52, 0x61, 0x74, 0x65, 0x22, 0x59, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49,
+ 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x64,
+ 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
+ 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64,
+ 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49,
+ 0x64, 0x22, 0xe5, 0x01, 0x0a, 0x1f, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74,
+ 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x0b, 0x32, 0x1b,
+ 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x6c, 0x61, 0x73,
+ 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x5e, 0x0a, 0x1d, 0x63, 0x6f, 0x6e,
+ 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74,
+ 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x1a, 0x63,
+ 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x4d, 0x61, 0x72, 0x6b, 0x44, 0x65, 0x6c, 0x65, 0x74,
+ 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x1b, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x4f, 0x66,
+ 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d,
+ 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x4e, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x54, 0x6f,
+ 0x70, 0x69, 0x63, 0x73, 0x4f, 0x66, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e,
+ 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x0a, 0x50, 0x45, 0x52, 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54,
+ 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73,
+ 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
+ 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x48, 0x61, 0x73, 0x68, 0x22, 0x33,
+ 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52, 0x53, 0x49, 0x53,
+ 0x54, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x45,
+ 0x52, 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c,
+ 0x4c, 0x10, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x23, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47,
+ 0x65, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x4f, 0x66, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52,
+ 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6f,
+ 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69,
+ 0x63, 0x73, 0x12, 0x21, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x08, 0x66, 0x69, 0x6c,
+ 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x5f,
+ 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x69,
+ 0x63, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1e, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
+ 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x07, 0x63,
+ 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0xbb, 0x01, 0x0a, 0x15, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x57, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74,
+ 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01,
+ 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12,
+ 0x1d, 0x0a, 0x0a, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
+ 0x02, 0x28, 0x04, 0x52, 0x09, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1c,
+ 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x02, 0x28,
+ 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e,
+ 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x04,
+ 0x20, 0x02, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x50, 0x61, 0x74, 0x74,
+ 0x65, 0x72, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x5f, 0x68, 0x61,
+ 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73,
+ 0x48, 0x61, 0x73, 0x68, 0x22, 0x93, 0x01, 0x0a, 0x1c, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x57, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x5f,
+ 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65,
+ 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x03, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x70,
+ 0x69, 0x63, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x02, 0x28, 0x09, 0x52, 0x0a,
+ 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x48, 0x61, 0x73, 0x68, 0x22, 0x9f, 0x01, 0x0a, 0x17, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x57, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63,
+ 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65,
+ 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x77, 0x61, 0x74, 0x63,
+ 0x68, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x6f, 0x70,
+ 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x77, 0x54, 0x6f,
+ 0x70, 0x69, 0x63, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f,
+ 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65,
+ 0x6c, 0x65, 0x74, 0x65, 0x64, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74,
+ 0x6f, 0x70, 0x69, 0x63, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x02, 0x28, 0x09,
+ 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x48, 0x61, 0x73, 0x68, 0x22, 0x5a, 0x0a, 0x1a,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x57, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69,
+ 0x63, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x77, 0x61, 0x74,
+ 0x63, 0x68, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x77,
+ 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x49, 0x64, 0x22, 0x6e, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1d, 0x0a, 0x0a,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04,
+ 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74,
+ 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69,
+ 0x63, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x63, 0x68, 0x65, 0x6d,
+ 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xed, 0x01, 0x0a, 0x18, 0x43, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f,
+ 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72,
+ 0x72, 0x6f, 0x72, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23,
+ 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d,
+ 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x63, 0x68, 0x65, 0x6d,
+ 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x7d, 0x0a, 0x18, 0x43, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x63,
+ 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x02,
+ 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x2c, 0x0a, 0x06, 0x73, 0x63, 0x68,
+ 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x02, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52,
+ 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xc7, 0x01, 0x0a, 0x20, 0x43, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x63,
+ 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04,
+ 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0a, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x63,
+ 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
+ 0x6e, 0x22, 0x56, 0x0a, 0x1d, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x63, 0x43, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64,
+ 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49,
+ 0x64, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04,
+ 0x3a, 0x01, 0x30, 0x52, 0x04, 0x74, 0x63, 0x49, 0x64, 0x22, 0x8a, 0x01, 0x0a, 0x1e, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x63, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
+ 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04,
+ 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x05, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x71, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x4e, 0x65, 0x77, 0x54, 0x78, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x5f, 0x74, 0x74,
+ 0x6c, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x3a,
+ 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x54, 0x74, 0x6c, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64,
+ 0x73, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
+ 0x3a, 0x01, 0x30, 0x52, 0x04, 0x74, 0x63, 0x49, 0x64, 0x22, 0xd9, 0x01, 0x0a, 0x15, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4e, 0x65, 0x77, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69,
+ 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73,
+ 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52,
+ 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12,
+ 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69,
+ 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e,
+ 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45,
+ 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x18, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54,
+ 0x78, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64,
+ 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49,
+ 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74,
+ 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e,
+ 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29,
+ 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74,
+ 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69,
+ 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x72,
+ 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70,
+ 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe4, 0x01, 0x0a, 0x20, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x54, 0x6f, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d,
+ 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02,
+ 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a,
+ 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69,
+ 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78,
+ 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73,
+ 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52,
+ 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x22, 0x48, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52,
+ 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x75,
+ 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xd4, 0x01, 0x0a, 0x1b, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e,
+ 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61,
+ 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f,
+ 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a,
+ 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74,
+ 0x73, 0x12, 0x3e, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x22, 0xe7, 0x01, 0x0a, 0x23, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x64, 0x64,
+ 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78,
+ 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69,
+ 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73,
+ 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d,
+ 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01,
+ 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73,
+ 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xbe, 0x01, 0x0a, 0x0d,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28,
+ 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10,
+ 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64,
+ 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e,
+ 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74,
+ 0x42, 0x69, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x0a, 0x74, 0x78, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x78, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x52, 0x09, 0x74, 0x78, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xd9, 0x01, 0x0a,
+ 0x15, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c,
+ 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x3a,
+ 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69,
+ 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74,
+ 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0d,
+ 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x2f, 0x0a,
+ 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70,
+ 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18,
+ 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa8, 0x02, 0x0a, 0x18, 0x43, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x50, 0x61, 0x72, 0x74,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65,
+ 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01,
+ 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x42, 0x69, 0x74,
+ 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x5f,
+ 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0d, 0x74,
+ 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05,
+ 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70,
+ 0x69, 0x63, 0x12, 0x36, 0x0a, 0x0a, 0x74, 0x78, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x78, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+ 0x09, 0x74, 0x78, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x21, 0x74, 0x78,
+ 0x6e, 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x5f, 0x6f,
+ 0x66, 0x5f, 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1c, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73,
+ 0x74, 0x42, 0x69, 0x74, 0x73, 0x4f, 0x66, 0x4c, 0x6f, 0x77, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d,
+ 0x61, 0x72, 0x6b, 0x22, 0xe4, 0x01, 0x0a, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45,
+ 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e, 0x69, 0x64,
+ 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74,
+ 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f, 0x6d, 0x6f,
+ 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30,
+ 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12,
+ 0x2f, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19,
+ 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd5, 0x02, 0x0a, 0x1b, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x53, 0x75,
+ 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e,
+ 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61,
+ 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f,
+ 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a,
+ 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74,
+ 0x73, 0x12, 0x3e, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x12, 0x36, 0x0a, 0x0a, 0x74, 0x78, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x78, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09,
+ 0x74, 0x78, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x21, 0x74, 0x78, 0x6e,
+ 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x5f, 0x6f, 0x66,
+ 0x5f, 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x1c, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61, 0x73, 0x74,
+ 0x42, 0x69, 0x74, 0x73, 0x4f, 0x66, 0x4c, 0x6f, 0x77, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61,
+ 0x72, 0x6b, 0x22, 0xe7, 0x01, 0x0a, 0x23, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e,
+ 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x74, 0x78, 0x6e,
+ 0x69, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x04, 0x3a, 0x01, 0x30, 0x52, 0x0e, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4c, 0x65, 0x61,
+ 0x73, 0x74, 0x42, 0x69, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x5f,
+ 0x6d, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x3a,
+ 0x01, 0x30, 0x52, 0x0d, 0x74, 0x78, 0x6e, 0x69, 0x64, 0x4d, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x74,
+ 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e,
+ 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x9a, 0x2e, 0x0a,
+ 0x0b, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x32, 0x0a, 0x04,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
+ 0x12, 0x36, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52,
+ 0x07, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x3c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e,
+ 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x09, 0x63, 0x6f, 0x6e,
+ 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x3c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72,
+ 0x69, 0x62, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63,
+ 0x72, 0x69, 0x62, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
+ 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x65, 0x72, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x12,
+ 0x2d, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e,
+ 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x64, 0x12, 0x43,
+ 0x0a, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x18, 0x07,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x52,
+ 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x63, 0x65,
+ 0x69, 0x70, 0x74, 0x12, 0x3d, 0x0a, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65,
+ 0x6e, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x45, 0x72, 0x72,
+ 0x6f, 0x72, 0x12, 0x36, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x03, 0x61, 0x63,
+ 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x63,
+ 0x6b, 0x52, 0x03, 0x61, 0x63, 0x6b, 0x12, 0x2d, 0x0a, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x0b,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x46, 0x6c, 0x6f, 0x77, 0x52,
+ 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x42, 0x0a, 0x0b, 0x75, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63,
+ 0x72, 0x69, 0x62, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x0b, 0x75, 0x6e,
+ 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x73, 0x75, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73,
+ 0x73, 0x12, 0x30, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1a, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x12, 0x49, 0x0a, 0x0e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x52,
+ 0x0d, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x12, 0x49,
+ 0x0a, 0x0e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
+ 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6c, 0x6f,
+ 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x0d, 0x63, 0x6c, 0x6f, 0x73,
+ 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x10, 0x70, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x11, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63,
+ 0x65, 0x72, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x64, 0x75,
+ 0x63, 0x65, 0x72, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x2d, 0x0a, 0x04, 0x70, 0x69,
+ 0x6e, 0x67, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50,
+ 0x69, 0x6e, 0x67, 0x52, 0x04, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x2d, 0x0a, 0x04, 0x70, 0x6f, 0x6e,
+ 0x67, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x6f,
+ 0x6e, 0x67, 0x52, 0x04, 0x70, 0x6f, 0x6e, 0x67, 0x12, 0x7e, 0x0a, 0x1f, 0x72, 0x65, 0x64, 0x65,
+ 0x6c, 0x69, 0x76, 0x65, 0x72, 0x55, 0x6e, 0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64,
+ 0x67, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65,
+ 0x72, 0x55, 0x6e, 0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x64, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x1f, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x69, 0x76,
+ 0x65, 0x72, 0x55, 0x6e, 0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x64,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x74,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x15, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x52, 0x11, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x73, 0x0a, 0x19, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50,
+ 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52,
+ 0x19, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0b, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x20, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70, 0x69,
+ 0x63, 0x52, 0x0b, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x5a,
+ 0x0a, 0x13, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x13, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x6f, 0x70,
+ 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x63, 0x6f,
+ 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x73, 0x12, 0x60, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x1a, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d,
+ 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52,
+ 0x15, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x11, 0x72, 0x65, 0x61, 0x63, 0x68, 0x65,
+ 0x64, 0x45, 0x6e, 0x64, 0x4f, 0x66, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x1b, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45,
+ 0x6e, 0x64, 0x4f, 0x66, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x52, 0x11, 0x72, 0x65, 0x61, 0x63, 0x68,
+ 0x65, 0x64, 0x45, 0x6e, 0x64, 0x4f, 0x66, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x2d, 0x0a, 0x04,
+ 0x73, 0x65, 0x65, 0x6b, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x53, 0x65, 0x65, 0x6b, 0x52, 0x04, 0x73, 0x65, 0x65, 0x6b, 0x12, 0x51, 0x0a, 0x10, 0x67,
+ 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x18,
+ 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x4c,
+ 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x52, 0x10, 0x67, 0x65,
+ 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x69,
+ 0x0a, 0x18, 0x67, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x2d, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52,
+ 0x18, 0x67, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49,
+ 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x16, 0x61, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x63, 0x68, 0x61,
+ 0x6e, 0x67, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x43, 0x68,
+ 0x61, 0x6e, 0x67, 0x65, 0x52, 0x14, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x73,
+ 0x75, 0x6d, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x5d, 0x0a, 0x14, 0x67, 0x65,
+ 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x4f, 0x66, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
+ 0x63, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47,
+ 0x65, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x4f, 0x66, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x52, 0x14, 0x67, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x4f, 0x66,
+ 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x75, 0x0a, 0x1c, 0x67, 0x65, 0x74,
+ 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x4f, 0x66, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
+ 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x31, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x4f,
+ 0x66, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x52, 0x1c, 0x67, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x4f, 0x66, 0x4e,
+ 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x12, 0x3c, 0x0a, 0x09, 0x67, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x22, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68,
+ 0x65, 0x6d, 0x61, 0x52, 0x09, 0x67, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x54,
+ 0x0a, 0x11, 0x67, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x52, 0x11, 0x67, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x43, 0x68, 0x61, 0x6c,
+ 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x41, 0x75, 0x74, 0x68, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52,
+ 0x0d, 0x61, 0x75, 0x74, 0x68, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x45,
+ 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x25,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x75, 0x74, 0x68, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0b, 0x61, 0x63,
+ 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x11, 0x67, 0x65, 0x74,
+ 0x4f, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x27,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x4f, 0x72,
+ 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x11, 0x67, 0x65,
+ 0x74, 0x4f, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12,
+ 0x6c, 0x0a, 0x19, 0x67, 0x65, 0x74, 0x4f, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x63,
+ 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x28, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x43, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x52, 0x19, 0x67, 0x65, 0x74, 0x4f, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53,
+ 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a,
+ 0x06, 0x6e, 0x65, 0x77, 0x54, 0x78, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+ 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x4e, 0x65, 0x77, 0x54, 0x78, 0x6e, 0x52, 0x06, 0x6e, 0x65, 0x77, 0x54,
+ 0x78, 0x6e, 0x12, 0x4b, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x4e, 0x65, 0x77, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52,
+ 0x0e, 0x6e, 0x65, 0x77, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+ 0x54, 0x0a, 0x11, 0x61, 0x64, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54,
+ 0x6f, 0x54, 0x78, 0x6e, 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54,
+ 0x78, 0x6e, 0x52, 0x11, 0x61, 0x64, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x54, 0x6f, 0x54, 0x78, 0x6e, 0x12, 0x6c, 0x0a, 0x19, 0x61, 0x64, 0x64, 0x50, 0x61, 0x72, 0x74,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41,
+ 0x64, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78, 0x6e,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x19, 0x61, 0x64, 0x64, 0x50, 0x61, 0x72,
+ 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x14, 0x61, 0x64, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78, 0x6e, 0x18, 0x36, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78, 0x6e, 0x52, 0x14, 0x61, 0x64,
+ 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54,
+ 0x78, 0x6e, 0x12, 0x75, 0x0a, 0x1c, 0x61, 0x64, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x18, 0x37, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41,
+ 0x64, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f,
+ 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x1c, 0x61, 0x64, 0x64,
+ 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x54, 0x78,
+ 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x65, 0x6e, 0x64,
+ 0x54, 0x78, 0x6e, 0x18, 0x38, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x75, 0x6c, 0x73,
+ 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+ 0x45, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x52, 0x06, 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x12, 0x4b,
+ 0x0a, 0x0e, 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x18, 0x39, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64,
+ 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0e, 0x65, 0x6e, 0x64,
+ 0x54, 0x78, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x11, 0x65,
+ 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x18, 0x3a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64,
+ 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11,
+ 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x12, 0x6c, 0x0a, 0x19, 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x50, 0x61, 0x72,
+ 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x3b,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x78,
+ 0x6e, 0x4f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x19, 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x50, 0x61,
+ 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+ 0x5d, 0x0a, 0x14, 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x53, 0x75, 0x62, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e,
+ 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x53, 0x75, 0x62, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x14, 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e,
+ 0x4f, 0x6e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x75,
+ 0x0a, 0x1c, 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f, 0x6e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x3d,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x78,
+ 0x6e, 0x4f, 0x6e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x1c, 0x65, 0x6e, 0x64, 0x54, 0x78, 0x6e, 0x4f,
+ 0x6e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x16, 0x74, 0x63, 0x43, 0x6c, 0x69, 0x65, 0x6e,
+ 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18,
+ 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x63, 0x43, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x52, 0x16, 0x74, 0x63, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e,
+ 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x66, 0x0a, 0x17, 0x74, 0x63,
+ 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x3f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x54, 0x63, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+ 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x17, 0x74, 0x63, 0x43, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63,
+ 0x4c, 0x69, 0x73, 0x74, 0x18, 0x40, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x75, 0x6c,
+ 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+ 0x64, 0x57, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x52,
+ 0x0e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x12,
+ 0x60, 0x0a, 0x15, 0x77, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4c, 0x69, 0x73,
+ 0x74, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x41, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a,
+ 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x57, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4c,
+ 0x69, 0x73, 0x74, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x15, 0x77, 0x61, 0x74, 0x63,
+ 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73,
+ 0x73, 0x12, 0x51, 0x0a, 0x10, 0x77, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x42, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x75,
+ 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x57, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61,
+ 0x74, 0x65, 0x52, 0x10, 0x77, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x55, 0x70,
+ 0x64, 0x61, 0x74, 0x65, 0x12, 0x5a, 0x0a, 0x13, 0x77, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70,
+ 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x18, 0x43, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x57, 0x61, 0x74, 0x63, 0x68, 0x54, 0x6f, 0x70,
+ 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x13, 0x77, 0x61, 0x74,
+ 0x63, 0x68, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65,
+ 0x22, 0x86, 0x0a, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x4e,
+ 0x4e, 0x45, 0x43, 0x54, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43,
+ 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49,
+ 0x42, 0x45, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x45, 0x52,
+ 0x10, 0x05, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x45, 0x4e, 0x44, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c,
+ 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x50, 0x54, 0x10, 0x07, 0x12, 0x0e,
+ 0x0a, 0x0a, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x08, 0x12, 0x0b,
+ 0x0a, 0x07, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x09, 0x12, 0x07, 0x0a, 0x03, 0x41,
+ 0x43, 0x4b, 0x10, 0x0a, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x4c, 0x4f, 0x57, 0x10, 0x0b, 0x12, 0x0f,
+ 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x42, 0x45, 0x10, 0x0c, 0x12,
+ 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x0d, 0x12, 0x09, 0x0a, 0x05,
+ 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x0e, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x4f, 0x53, 0x45,
+ 0x5f, 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x45, 0x52, 0x10, 0x0f, 0x12, 0x12, 0x0a, 0x0e, 0x43,
+ 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x55, 0x4d, 0x45, 0x52, 0x10, 0x10, 0x12,
+ 0x14, 0x0a, 0x10, 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x43, 0x43,
+ 0x45, 0x53, 0x53, 0x10, 0x11, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x12, 0x12,
+ 0x08, 0x0a, 0x04, 0x50, 0x4f, 0x4e, 0x47, 0x10, 0x13, 0x12, 0x25, 0x0a, 0x21, 0x52, 0x45, 0x44,
+ 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x41, 0x43, 0x4b, 0x4e, 0x4f, 0x57, 0x4c,
+ 0x45, 0x44, 0x47, 0x45, 0x44, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x53, 0x10, 0x14,
+ 0x12, 0x18, 0x0a, 0x14, 0x50, 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x45, 0x44, 0x5f,
+ 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x10, 0x15, 0x12, 0x21, 0x0a, 0x1d, 0x50, 0x41,
+ 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x45, 0x44, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41,
+ 0x54, 0x41, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x16, 0x12, 0x0a, 0x0a,
+ 0x06, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x10, 0x17, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x4f,
+ 0x4b, 0x55, 0x50, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x18, 0x12, 0x12,
+ 0x0a, 0x0e, 0x43, 0x4f, 0x4e, 0x53, 0x55, 0x4d, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x53,
+ 0x10, 0x19, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4f, 0x4e, 0x53, 0x55, 0x4d, 0x45, 0x52, 0x5f, 0x53,
+ 0x54, 0x41, 0x54, 0x53, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x1a, 0x12,
+ 0x18, 0x0a, 0x14, 0x52, 0x45, 0x41, 0x43, 0x48, 0x45, 0x44, 0x5f, 0x45, 0x4e, 0x44, 0x5f, 0x4f,
+ 0x46, 0x5f, 0x54, 0x4f, 0x50, 0x49, 0x43, 0x10, 0x1b, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x45, 0x45,
+ 0x4b, 0x10, 0x1c, 0x12, 0x17, 0x0a, 0x13, 0x47, 0x45, 0x54, 0x5f, 0x4c, 0x41, 0x53, 0x54, 0x5f,
+ 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x49, 0x44, 0x10, 0x1d, 0x12, 0x20, 0x0a, 0x1c,
+ 0x47, 0x45, 0x54, 0x5f, 0x4c, 0x41, 0x53, 0x54, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45,
+ 0x5f, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x1e, 0x12, 0x1a,
+ 0x0a, 0x16, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x55, 0x4d, 0x45,
+ 0x52, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x1f, 0x12, 0x1b, 0x0a, 0x17, 0x47, 0x45,
+ 0x54, 0x5f, 0x54, 0x4f, 0x50, 0x49, 0x43, 0x53, 0x5f, 0x4f, 0x46, 0x5f, 0x4e, 0x41, 0x4d, 0x45,
+ 0x53, 0x50, 0x41, 0x43, 0x45, 0x10, 0x20, 0x12, 0x24, 0x0a, 0x20, 0x47, 0x45, 0x54, 0x5f, 0x54,
+ 0x4f, 0x50, 0x49, 0x43, 0x53, 0x5f, 0x4f, 0x46, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x50, 0x41,
+ 0x43, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x21, 0x12, 0x0e, 0x0a,
+ 0x0a, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x10, 0x22, 0x12, 0x17, 0x0a,
+ 0x13, 0x47, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x5f, 0x52, 0x45, 0x53, 0x50,
+ 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x23, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x43,
+ 0x48, 0x41, 0x4c, 0x4c, 0x45, 0x4e, 0x47, 0x45, 0x10, 0x24, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55,
+ 0x54, 0x48, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x25, 0x12, 0x10, 0x0a,
+ 0x0c, 0x41, 0x43, 0x4b, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x26, 0x12,
+ 0x18, 0x0a, 0x14, 0x47, 0x45, 0x54, 0x5f, 0x4f, 0x52, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45,
+ 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x10, 0x27, 0x12, 0x21, 0x0a, 0x1d, 0x47, 0x45, 0x54,
+ 0x5f, 0x4f, 0x52, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d,
+ 0x41, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x28, 0x12, 0x0b, 0x0a, 0x07,
+ 0x4e, 0x45, 0x57, 0x5f, 0x54, 0x58, 0x4e, 0x10, 0x32, 0x12, 0x14, 0x0a, 0x10, 0x4e, 0x45, 0x57,
+ 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x33, 0x12,
+ 0x18, 0x0a, 0x14, 0x41, 0x44, 0x44, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e,
+ 0x5f, 0x54, 0x4f, 0x5f, 0x54, 0x58, 0x4e, 0x10, 0x34, 0x12, 0x21, 0x0a, 0x1d, 0x41, 0x44, 0x44,
+ 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x4f, 0x5f, 0x54, 0x58,
+ 0x4e, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x35, 0x12, 0x1b, 0x0a, 0x17,
+ 0x41, 0x44, 0x44, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e,
+ 0x5f, 0x54, 0x4f, 0x5f, 0x54, 0x58, 0x4e, 0x10, 0x36, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x44, 0x44,
+ 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x4f,
+ 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x37, 0x12,
+ 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x58, 0x4e, 0x10, 0x38, 0x12, 0x14, 0x0a, 0x10,
+ 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45,
+ 0x10, 0x39, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x4f, 0x4e,
+ 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x3a, 0x12, 0x21, 0x0a, 0x1d,
+ 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49,
+ 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x3b, 0x12,
+ 0x1b, 0x0a, 0x17, 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x4f, 0x4e, 0x5f, 0x53, 0x55,
+ 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x3c, 0x12, 0x24, 0x0a, 0x20,
+ 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x58, 0x4e, 0x5f, 0x4f, 0x4e, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43,
+ 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45,
+ 0x10, 0x3d, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x43, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f,
+ 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10,
+ 0x3e, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x43, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x43,
+ 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10,
+ 0x3f, 0x12, 0x14, 0x0a, 0x10, 0x57, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x4f, 0x50, 0x49, 0x43,
+ 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x40, 0x12, 0x1c, 0x0a, 0x18, 0x57, 0x41, 0x54, 0x43, 0x48,
+ 0x5f, 0x54, 0x4f, 0x50, 0x49, 0x43, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x53, 0x55, 0x43, 0x43,
+ 0x45, 0x53, 0x53, 0x10, 0x41, 0x12, 0x16, 0x0a, 0x12, 0x57, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54,
+ 0x4f, 0x50, 0x49, 0x43, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x42, 0x12, 0x1a, 0x0a,
+ 0x16, 0x57, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x4f, 0x50, 0x49, 0x43, 0x5f, 0x4c, 0x49, 0x53,
+ 0x54, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x10, 0x43, 0x2a, 0x44, 0x0a, 0x0f, 0x43, 0x6f, 0x6d,
+ 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04,
+ 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x5a, 0x34, 0x10, 0x01, 0x12,
+ 0x08, 0x0a, 0x04, 0x5a, 0x4c, 0x49, 0x42, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x53, 0x54,
+ 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x4e, 0x41, 0x50, 0x50, 0x59, 0x10, 0x04, 0x2a,
+ 0x5f, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73,
+ 0x73, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x10,
+ 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x10, 0x01,
+ 0x12, 0x14, 0x0a, 0x10, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x45, 0x78, 0x63, 0x6c, 0x75,
+ 0x73, 0x69, 0x76, 0x65, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x73,
+ 0x69, 0x76, 0x65, 0x57, 0x69, 0x74, 0x68, 0x46, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x10, 0x03,
+ 0x2a, 0x82, 0x05, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72,
+ 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72,
+ 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x72,
+ 0x72, 0x6f, 0x72, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74,
+ 0x65, 0x6e, 0x63, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x41,
+ 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72,
+ 0x6f, 0x72, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c,
+ 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x42, 0x75, 0x73, 0x79, 0x10, 0x05, 0x12, 0x13,
+ 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64,
+ 0x79, 0x10, 0x06, 0x12, 0x25, 0x0a, 0x21, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x42,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x45, 0x78, 0x63, 0x65, 0x65,
+ 0x64, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x07, 0x12, 0x29, 0x0a, 0x25, 0x50, 0x72,
+ 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x51, 0x75, 0x6f,
+ 0x74, 0x61, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75,
+ 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x09, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x6e, 0x73, 0x75,
+ 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x72,
+ 0x72, 0x6f, 0x72, 0x10, 0x0a, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4e, 0x6f,
+ 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0x0b, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64,
+ 0x10, 0x0c, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x4e, 0x6f,
+ 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10, 0x0d, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x6f, 0x6f, 0x4d,
+ 0x61, 0x6e, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x10, 0x0e, 0x12, 0x18, 0x0a,
+ 0x14, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64,
+ 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x0f, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x64, 0x75,
+ 0x63, 0x65, 0x72, 0x42, 0x75, 0x73, 0x79, 0x10, 0x10, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x76,
+ 0x61, 0x6c, 0x69, 0x64, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x10, 0x11, 0x12,
+ 0x16, 0x0a, 0x12, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53,
+ 0x63, 0x68, 0x65, 0x6d, 0x61, 0x10, 0x12, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x73, 0x75,
+ 0x6d, 0x65, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x13,
+ 0x12, 0x22, 0x0a, 0x1e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43,
+ 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75,
+ 0x6e, 0x64, 0x10, 0x14, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x54,
+ 0x78, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0x15, 0x12, 0x13, 0x0a, 0x0f, 0x4e, 0x6f,
+ 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x16, 0x12,
+ 0x17, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
+ 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x10, 0x17, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x6e,
+ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x10,
+ 0x18, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x46, 0x65, 0x6e,
+ 0x63, 0x65, 0x64, 0x10, 0x19, 0x2a, 0x4b, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74,
+ 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f,
+ 0x64, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x75, 0x74, 0x68, 0x4d,
+ 0x65, 0x74, 0x68, 0x6f, 0x64, 0x59, 0x63, 0x61, 0x56, 0x31, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10,
+ 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73,
+ 0x10, 0x02, 0x2a, 0xbb, 0x01, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56,
+ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x06, 0x0a, 0x02, 0x76, 0x30, 0x10, 0x00, 0x12, 0x06,
+ 0x0a, 0x02, 0x76, 0x31, 0x10, 0x01, 0x12, 0x06, 0x0a, 0x02, 0x76, 0x32, 0x10, 0x02, 0x12, 0x06,
+ 0x0a, 0x02, 0x76, 0x33, 0x10, 0x03, 0x12, 0x06, 0x0a, 0x02, 0x76, 0x34, 0x10, 0x04, 0x12, 0x06,
+ 0x0a, 0x02, 0x76, 0x35, 0x10, 0x05, 0x12, 0x06, 0x0a, 0x02, 0x76, 0x36, 0x10, 0x06, 0x12, 0x06,
+ 0x0a, 0x02, 0x76, 0x37, 0x10, 0x07, 0x12, 0x06, 0x0a, 0x02, 0x76, 0x38, 0x10, 0x08, 0x12, 0x06,
+ 0x0a, 0x02, 0x76, 0x39, 0x10, 0x09, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x31, 0x30, 0x10, 0x0a, 0x12,
+ 0x07, 0x0a, 0x03, 0x76, 0x31, 0x31, 0x10, 0x0b, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x31, 0x32, 0x10,
+ 0x0c, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x31, 0x33, 0x10, 0x0d, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x31,
+ 0x34, 0x10, 0x0e, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x31, 0x35, 0x10, 0x0f, 0x12, 0x07, 0x0a, 0x03,
+ 0x76, 0x31, 0x36, 0x10, 0x10, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x31, 0x37, 0x10, 0x11, 0x12, 0x07,
+ 0x0a, 0x03, 0x76, 0x31, 0x38, 0x10, 0x12, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x31, 0x39, 0x10, 0x13,
+ 0x2a, 0x2b, 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4d, 0x6f, 0x64,
+ 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x53, 0x50, 0x4c, 0x49, 0x54, 0x10,
+ 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x49, 0x43, 0x4b, 0x59, 0x10, 0x01, 0x2a, 0x22, 0x0a,
+ 0x09, 0x54, 0x78, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f,
+ 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10,
+ 0x01, 0x42, 0x2f, 0x0a, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e,
+ 0x70, 0x75, 0x6c, 0x73, 0x61, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x70,
+ 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x03, 0x5a, 0x07, 0x2e, 0x2f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f,
+}
+
+var (
+ file_PulsarApi_proto_rawDescOnce sync.Once
+ file_PulsarApi_proto_rawDescData = file_PulsarApi_proto_rawDesc
+)
+
+func file_PulsarApi_proto_rawDescGZIP() []byte {
+ file_PulsarApi_proto_rawDescOnce.Do(func() {
+ file_PulsarApi_proto_rawDescData = protoimpl.X.CompressGZIP(file_PulsarApi_proto_rawDescData)
+ })
+ return file_PulsarApi_proto_rawDescData
+}
+
+var file_PulsarApi_proto_enumTypes = make([]protoimpl.EnumInfo, 16)
+var file_PulsarApi_proto_msgTypes = make([]protoimpl.MessageInfo, 71)
+var file_PulsarApi_proto_goTypes = []interface{}{
+ (CompressionType)(0), // 0: pulsar.proto.CompressionType
+ (ProducerAccessMode)(0), // 1: pulsar.proto.ProducerAccessMode
+ (ServerError)(0), // 2: pulsar.proto.ServerError
+ (AuthMethod)(0), // 3: pulsar.proto.AuthMethod
+ (ProtocolVersion)(0), // 4: pulsar.proto.ProtocolVersion
+ (KeySharedMode)(0), // 5: pulsar.proto.KeySharedMode
+ (TxnAction)(0), // 6: pulsar.proto.TxnAction
+ (Schema_Type)(0), // 7: pulsar.proto.Schema.Type
+ (CommandSubscribe_SubType)(0), // 8: pulsar.proto.CommandSubscribe.SubType
+ (CommandSubscribe_InitialPosition)(0), // 9: pulsar.proto.CommandSubscribe.InitialPosition
+ (CommandPartitionedTopicMetadataResponse_LookupType)(0), // 10: pulsar.proto.CommandPartitionedTopicMetadataResponse.LookupType
+ (CommandLookupTopicResponse_LookupType)(0), // 11: pulsar.proto.CommandLookupTopicResponse.LookupType
+ (CommandAck_AckType)(0), // 12: pulsar.proto.CommandAck.AckType
+ (CommandAck_ValidationError)(0), // 13: pulsar.proto.CommandAck.ValidationError
+ (CommandGetTopicsOfNamespace_Mode)(0), // 14: pulsar.proto.CommandGetTopicsOfNamespace.Mode
+ (BaseCommand_Type)(0), // 15: pulsar.proto.BaseCommand.Type
+ (*Schema)(nil), // 16: pulsar.proto.Schema
+ (*MessageIdData)(nil), // 17: pulsar.proto.MessageIdData
+ (*KeyValue)(nil), // 18: pulsar.proto.KeyValue
+ (*KeyLongValue)(nil), // 19: pulsar.proto.KeyLongValue
+ (*IntRange)(nil), // 20: pulsar.proto.IntRange
+ (*EncryptionKeys)(nil), // 21: pulsar.proto.EncryptionKeys
+ (*MessageMetadata)(nil), // 22: pulsar.proto.MessageMetadata
+ (*SingleMessageMetadata)(nil), // 23: pulsar.proto.SingleMessageMetadata
+ (*BrokerEntryMetadata)(nil), // 24: pulsar.proto.BrokerEntryMetadata
+ (*CommandConnect)(nil), // 25: pulsar.proto.CommandConnect
+ (*FeatureFlags)(nil), // 26: pulsar.proto.FeatureFlags
+ (*CommandConnected)(nil), // 27: pulsar.proto.CommandConnected
+ (*CommandAuthResponse)(nil), // 28: pulsar.proto.CommandAuthResponse
+ (*CommandAuthChallenge)(nil), // 29: pulsar.proto.CommandAuthChallenge
+ (*AuthData)(nil), // 30: pulsar.proto.AuthData
+ (*KeySharedMeta)(nil), // 31: pulsar.proto.KeySharedMeta
+ (*CommandSubscribe)(nil), // 32: pulsar.proto.CommandSubscribe
+ (*CommandPartitionedTopicMetadata)(nil), // 33: pulsar.proto.CommandPartitionedTopicMetadata
+ (*CommandPartitionedTopicMetadataResponse)(nil), // 34: pulsar.proto.CommandPartitionedTopicMetadataResponse
+ (*CommandLookupTopic)(nil), // 35: pulsar.proto.CommandLookupTopic
+ (*CommandLookupTopicResponse)(nil), // 36: pulsar.proto.CommandLookupTopicResponse
+ (*CommandProducer)(nil), // 37: pulsar.proto.CommandProducer
+ (*CommandSend)(nil), // 38: pulsar.proto.CommandSend
+ (*CommandSendReceipt)(nil), // 39: pulsar.proto.CommandSendReceipt
+ (*CommandSendError)(nil), // 40: pulsar.proto.CommandSendError
+ (*CommandMessage)(nil), // 41: pulsar.proto.CommandMessage
+ (*CommandAck)(nil), // 42: pulsar.proto.CommandAck
+ (*CommandAckResponse)(nil), // 43: pulsar.proto.CommandAckResponse
+ (*CommandActiveConsumerChange)(nil), // 44: pulsar.proto.CommandActiveConsumerChange
+ (*CommandFlow)(nil), // 45: pulsar.proto.CommandFlow
+ (*CommandUnsubscribe)(nil), // 46: pulsar.proto.CommandUnsubscribe
+ (*CommandSeek)(nil), // 47: pulsar.proto.CommandSeek
+ (*CommandReachedEndOfTopic)(nil), // 48: pulsar.proto.CommandReachedEndOfTopic
+ (*CommandCloseProducer)(nil), // 49: pulsar.proto.CommandCloseProducer
+ (*CommandCloseConsumer)(nil), // 50: pulsar.proto.CommandCloseConsumer
+ (*CommandRedeliverUnacknowledgedMessages)(nil), // 51: pulsar.proto.CommandRedeliverUnacknowledgedMessages
+ (*CommandSuccess)(nil), // 52: pulsar.proto.CommandSuccess
+ (*CommandProducerSuccess)(nil), // 53: pulsar.proto.CommandProducerSuccess
+ (*CommandError)(nil), // 54: pulsar.proto.CommandError
+ (*CommandPing)(nil), // 55: pulsar.proto.CommandPing
+ (*CommandPong)(nil), // 56: pulsar.proto.CommandPong
+ (*CommandConsumerStats)(nil), // 57: pulsar.proto.CommandConsumerStats
+ (*CommandConsumerStatsResponse)(nil), // 58: pulsar.proto.CommandConsumerStatsResponse
+ (*CommandGetLastMessageId)(nil), // 59: pulsar.proto.CommandGetLastMessageId
+ (*CommandGetLastMessageIdResponse)(nil), // 60: pulsar.proto.CommandGetLastMessageIdResponse
+ (*CommandGetTopicsOfNamespace)(nil), // 61: pulsar.proto.CommandGetTopicsOfNamespace
+ (*CommandGetTopicsOfNamespaceResponse)(nil), // 62: pulsar.proto.CommandGetTopicsOfNamespaceResponse
+ (*CommandWatchTopicList)(nil), // 63: pulsar.proto.CommandWatchTopicList
+ (*CommandWatchTopicListSuccess)(nil), // 64: pulsar.proto.CommandWatchTopicListSuccess
+ (*CommandWatchTopicUpdate)(nil), // 65: pulsar.proto.CommandWatchTopicUpdate
+ (*CommandWatchTopicListClose)(nil), // 66: pulsar.proto.CommandWatchTopicListClose
+ (*CommandGetSchema)(nil), // 67: pulsar.proto.CommandGetSchema
+ (*CommandGetSchemaResponse)(nil), // 68: pulsar.proto.CommandGetSchemaResponse
+ (*CommandGetOrCreateSchema)(nil), // 69: pulsar.proto.CommandGetOrCreateSchema
+ (*CommandGetOrCreateSchemaResponse)(nil), // 70: pulsar.proto.CommandGetOrCreateSchemaResponse
+ (*CommandTcClientConnectRequest)(nil), // 71: pulsar.proto.CommandTcClientConnectRequest
+ (*CommandTcClientConnectResponse)(nil), // 72: pulsar.proto.CommandTcClientConnectResponse
+ (*CommandNewTxn)(nil), // 73: pulsar.proto.CommandNewTxn
+ (*CommandNewTxnResponse)(nil), // 74: pulsar.proto.CommandNewTxnResponse
+ (*CommandAddPartitionToTxn)(nil), // 75: pulsar.proto.CommandAddPartitionToTxn
+ (*CommandAddPartitionToTxnResponse)(nil), // 76: pulsar.proto.CommandAddPartitionToTxnResponse
+ (*Subscription)(nil), // 77: pulsar.proto.Subscription
+ (*CommandAddSubscriptionToTxn)(nil), // 78: pulsar.proto.CommandAddSubscriptionToTxn
+ (*CommandAddSubscriptionToTxnResponse)(nil), // 79: pulsar.proto.CommandAddSubscriptionToTxnResponse
+ (*CommandEndTxn)(nil), // 80: pulsar.proto.CommandEndTxn
+ (*CommandEndTxnResponse)(nil), // 81: pulsar.proto.CommandEndTxnResponse
+ (*CommandEndTxnOnPartition)(nil), // 82: pulsar.proto.CommandEndTxnOnPartition
+ (*CommandEndTxnOnPartitionResponse)(nil), // 83: pulsar.proto.CommandEndTxnOnPartitionResponse
+ (*CommandEndTxnOnSubscription)(nil), // 84: pulsar.proto.CommandEndTxnOnSubscription
+ (*CommandEndTxnOnSubscriptionResponse)(nil), // 85: pulsar.proto.CommandEndTxnOnSubscriptionResponse
+ (*BaseCommand)(nil), // 86: pulsar.proto.BaseCommand
+}
+var file_PulsarApi_proto_depIdxs = []int32{
+ 7, // 0: pulsar.proto.Schema.type:type_name -> pulsar.proto.Schema.Type
+ 18, // 1: pulsar.proto.Schema.properties:type_name -> pulsar.proto.KeyValue
+ 17, // 2: pulsar.proto.MessageIdData.first_chunk_message_id:type_name -> pulsar.proto.MessageIdData
+ 18, // 3: pulsar.proto.EncryptionKeys.metadata:type_name -> pulsar.proto.KeyValue
+ 18, // 4: pulsar.proto.MessageMetadata.properties:type_name -> pulsar.proto.KeyValue
+ 0, // 5: pulsar.proto.MessageMetadata.compression:type_name -> pulsar.proto.CompressionType
+ 21, // 6: pulsar.proto.MessageMetadata.encryption_keys:type_name -> pulsar.proto.EncryptionKeys
+ 18, // 7: pulsar.proto.SingleMessageMetadata.properties:type_name -> pulsar.proto.KeyValue
+ 3, // 8: pulsar.proto.CommandConnect.auth_method:type_name -> pulsar.proto.AuthMethod
+ 26, // 9: pulsar.proto.CommandConnect.feature_flags:type_name -> pulsar.proto.FeatureFlags
+ 26, // 10: pulsar.proto.CommandConnected.feature_flags:type_name -> pulsar.proto.FeatureFlags
+ 30, // 11: pulsar.proto.CommandAuthResponse.response:type_name -> pulsar.proto.AuthData
+ 30, // 12: pulsar.proto.CommandAuthChallenge.challenge:type_name -> pulsar.proto.AuthData
+ 5, // 13: pulsar.proto.KeySharedMeta.keySharedMode:type_name -> pulsar.proto.KeySharedMode
+ 20, // 14: pulsar.proto.KeySharedMeta.hashRanges:type_name -> pulsar.proto.IntRange
+ 8, // 15: pulsar.proto.CommandSubscribe.subType:type_name -> pulsar.proto.CommandSubscribe.SubType
+ 17, // 16: pulsar.proto.CommandSubscribe.start_message_id:type_name -> pulsar.proto.MessageIdData
+ 18, // 17: pulsar.proto.CommandSubscribe.metadata:type_name -> pulsar.proto.KeyValue
+ 16, // 18: pulsar.proto.CommandSubscribe.schema:type_name -> pulsar.proto.Schema
+ 9, // 19: pulsar.proto.CommandSubscribe.initialPosition:type_name -> pulsar.proto.CommandSubscribe.InitialPosition
+ 31, // 20: pulsar.proto.CommandSubscribe.keySharedMeta:type_name -> pulsar.proto.KeySharedMeta
+ 18, // 21: pulsar.proto.CommandSubscribe.subscription_properties:type_name -> pulsar.proto.KeyValue
+ 10, // 22: pulsar.proto.CommandPartitionedTopicMetadataResponse.response:type_name -> pulsar.proto.CommandPartitionedTopicMetadataResponse.LookupType
+ 2, // 23: pulsar.proto.CommandPartitionedTopicMetadataResponse.error:type_name -> pulsar.proto.ServerError
+ 11, // 24: pulsar.proto.CommandLookupTopicResponse.response:type_name -> pulsar.proto.CommandLookupTopicResponse.LookupType
+ 2, // 25: pulsar.proto.CommandLookupTopicResponse.error:type_name -> pulsar.proto.ServerError
+ 18, // 26: pulsar.proto.CommandProducer.metadata:type_name -> pulsar.proto.KeyValue
+ 16, // 27: pulsar.proto.CommandProducer.schema:type_name -> pulsar.proto.Schema
+ 1, // 28: pulsar.proto.CommandProducer.producer_access_mode:type_name -> pulsar.proto.ProducerAccessMode
+ 17, // 29: pulsar.proto.CommandSend.message_id:type_name -> pulsar.proto.MessageIdData
+ 17, // 30: pulsar.proto.CommandSendReceipt.message_id:type_name -> pulsar.proto.MessageIdData
+ 2, // 31: pulsar.proto.CommandSendError.error:type_name -> pulsar.proto.ServerError
+ 17, // 32: pulsar.proto.CommandMessage.message_id:type_name -> pulsar.proto.MessageIdData
+ 12, // 33: pulsar.proto.CommandAck.ack_type:type_name -> pulsar.proto.CommandAck.AckType
+ 17, // 34: pulsar.proto.CommandAck.message_id:type_name -> pulsar.proto.MessageIdData
+ 13, // 35: pulsar.proto.CommandAck.validation_error:type_name -> pulsar.proto.CommandAck.ValidationError
+ 19, // 36: pulsar.proto.CommandAck.properties:type_name -> pulsar.proto.KeyLongValue
+ 2, // 37: pulsar.proto.CommandAckResponse.error:type_name -> pulsar.proto.ServerError
+ 17, // 38: pulsar.proto.CommandSeek.message_id:type_name -> pulsar.proto.MessageIdData
+ 17, // 39: pulsar.proto.CommandRedeliverUnacknowledgedMessages.message_ids:type_name -> pulsar.proto.MessageIdData
+ 16, // 40: pulsar.proto.CommandSuccess.schema:type_name -> pulsar.proto.Schema
+ 2, // 41: pulsar.proto.CommandError.error:type_name -> pulsar.proto.ServerError
+ 2, // 42: pulsar.proto.CommandConsumerStatsResponse.error_code:type_name -> pulsar.proto.ServerError
+ 17, // 43: pulsar.proto.CommandGetLastMessageIdResponse.last_message_id:type_name -> pulsar.proto.MessageIdData
+ 17, // 44: pulsar.proto.CommandGetLastMessageIdResponse.consumer_mark_delete_position:type_name -> pulsar.proto.MessageIdData
+ 14, // 45: pulsar.proto.CommandGetTopicsOfNamespace.mode:type_name -> pulsar.proto.CommandGetTopicsOfNamespace.Mode
+ 2, // 46: pulsar.proto.CommandGetSchemaResponse.error_code:type_name -> pulsar.proto.ServerError
+ 16, // 47: pulsar.proto.CommandGetSchemaResponse.schema:type_name -> pulsar.proto.Schema
+ 16, // 48: pulsar.proto.CommandGetOrCreateSchema.schema:type_name -> pulsar.proto.Schema
+ 2, // 49: pulsar.proto.CommandGetOrCreateSchemaResponse.error_code:type_name -> pulsar.proto.ServerError
+ 2, // 50: pulsar.proto.CommandTcClientConnectResponse.error:type_name -> pulsar.proto.ServerError
+ 2, // 51: pulsar.proto.CommandNewTxnResponse.error:type_name -> pulsar.proto.ServerError
+ 2, // 52: pulsar.proto.CommandAddPartitionToTxnResponse.error:type_name -> pulsar.proto.ServerError
+ 77, // 53: pulsar.proto.CommandAddSubscriptionToTxn.subscription:type_name -> pulsar.proto.Subscription
+ 2, // 54: pulsar.proto.CommandAddSubscriptionToTxnResponse.error:type_name -> pulsar.proto.ServerError
+ 6, // 55: pulsar.proto.CommandEndTxn.txn_action:type_name -> pulsar.proto.TxnAction
+ 2, // 56: pulsar.proto.CommandEndTxnResponse.error:type_name -> pulsar.proto.ServerError
+ 6, // 57: pulsar.proto.CommandEndTxnOnPartition.txn_action:type_name -> pulsar.proto.TxnAction
+ 2, // 58: pulsar.proto.CommandEndTxnOnPartitionResponse.error:type_name -> pulsar.proto.ServerError
+ 77, // 59: pulsar.proto.CommandEndTxnOnSubscription.subscription:type_name -> pulsar.proto.Subscription
+ 6, // 60: pulsar.proto.CommandEndTxnOnSubscription.txn_action:type_name -> pulsar.proto.TxnAction
+ 2, // 61: pulsar.proto.CommandEndTxnOnSubscriptionResponse.error:type_name -> pulsar.proto.ServerError
+ 15, // 62: pulsar.proto.BaseCommand.type:type_name -> pulsar.proto.BaseCommand.Type
+ 25, // 63: pulsar.proto.BaseCommand.connect:type_name -> pulsar.proto.CommandConnect
+ 27, // 64: pulsar.proto.BaseCommand.connected:type_name -> pulsar.proto.CommandConnected
+ 32, // 65: pulsar.proto.BaseCommand.subscribe:type_name -> pulsar.proto.CommandSubscribe
+ 37, // 66: pulsar.proto.BaseCommand.producer:type_name -> pulsar.proto.CommandProducer
+ 38, // 67: pulsar.proto.BaseCommand.send:type_name -> pulsar.proto.CommandSend
+ 39, // 68: pulsar.proto.BaseCommand.send_receipt:type_name -> pulsar.proto.CommandSendReceipt
+ 40, // 69: pulsar.proto.BaseCommand.send_error:type_name -> pulsar.proto.CommandSendError
+ 41, // 70: pulsar.proto.BaseCommand.message:type_name -> pulsar.proto.CommandMessage
+ 42, // 71: pulsar.proto.BaseCommand.ack:type_name -> pulsar.proto.CommandAck
+ 45, // 72: pulsar.proto.BaseCommand.flow:type_name -> pulsar.proto.CommandFlow
+ 46, // 73: pulsar.proto.BaseCommand.unsubscribe:type_name -> pulsar.proto.CommandUnsubscribe
+ 52, // 74: pulsar.proto.BaseCommand.success:type_name -> pulsar.proto.CommandSuccess
+ 54, // 75: pulsar.proto.BaseCommand.error:type_name -> pulsar.proto.CommandError
+ 49, // 76: pulsar.proto.BaseCommand.close_producer:type_name -> pulsar.proto.CommandCloseProducer
+ 50, // 77: pulsar.proto.BaseCommand.close_consumer:type_name -> pulsar.proto.CommandCloseConsumer
+ 53, // 78: pulsar.proto.BaseCommand.producer_success:type_name -> pulsar.proto.CommandProducerSuccess
+ 55, // 79: pulsar.proto.BaseCommand.ping:type_name -> pulsar.proto.CommandPing
+ 56, // 80: pulsar.proto.BaseCommand.pong:type_name -> pulsar.proto.CommandPong
+ 51, // 81: pulsar.proto.BaseCommand.redeliverUnacknowledgedMessages:type_name -> pulsar.proto.CommandRedeliverUnacknowledgedMessages
+ 33, // 82: pulsar.proto.BaseCommand.partitionMetadata:type_name -> pulsar.proto.CommandPartitionedTopicMetadata
+ 34, // 83: pulsar.proto.BaseCommand.partitionMetadataResponse:type_name -> pulsar.proto.CommandPartitionedTopicMetadataResponse
+ 35, // 84: pulsar.proto.BaseCommand.lookupTopic:type_name -> pulsar.proto.CommandLookupTopic
+ 36, // 85: pulsar.proto.BaseCommand.lookupTopicResponse:type_name -> pulsar.proto.CommandLookupTopicResponse
+ 57, // 86: pulsar.proto.BaseCommand.consumerStats:type_name -> pulsar.proto.CommandConsumerStats
+ 58, // 87: pulsar.proto.BaseCommand.consumerStatsResponse:type_name -> pulsar.proto.CommandConsumerStatsResponse
+ 48, // 88: pulsar.proto.BaseCommand.reachedEndOfTopic:type_name -> pulsar.proto.CommandReachedEndOfTopic
+ 47, // 89: pulsar.proto.BaseCommand.seek:type_name -> pulsar.proto.CommandSeek
+ 59, // 90: pulsar.proto.BaseCommand.getLastMessageId:type_name -> pulsar.proto.CommandGetLastMessageId
+ 60, // 91: pulsar.proto.BaseCommand.getLastMessageIdResponse:type_name -> pulsar.proto.CommandGetLastMessageIdResponse
+ 44, // 92: pulsar.proto.BaseCommand.active_consumer_change:type_name -> pulsar.proto.CommandActiveConsumerChange
+ 61, // 93: pulsar.proto.BaseCommand.getTopicsOfNamespace:type_name -> pulsar.proto.CommandGetTopicsOfNamespace
+ 62, // 94: pulsar.proto.BaseCommand.getTopicsOfNamespaceResponse:type_name -> pulsar.proto.CommandGetTopicsOfNamespaceResponse
+ 67, // 95: pulsar.proto.BaseCommand.getSchema:type_name -> pulsar.proto.CommandGetSchema
+ 68, // 96: pulsar.proto.BaseCommand.getSchemaResponse:type_name -> pulsar.proto.CommandGetSchemaResponse
+ 29, // 97: pulsar.proto.BaseCommand.authChallenge:type_name -> pulsar.proto.CommandAuthChallenge
+ 28, // 98: pulsar.proto.BaseCommand.authResponse:type_name -> pulsar.proto.CommandAuthResponse
+ 43, // 99: pulsar.proto.BaseCommand.ackResponse:type_name -> pulsar.proto.CommandAckResponse
+ 69, // 100: pulsar.proto.BaseCommand.getOrCreateSchema:type_name -> pulsar.proto.CommandGetOrCreateSchema
+ 70, // 101: pulsar.proto.BaseCommand.getOrCreateSchemaResponse:type_name -> pulsar.proto.CommandGetOrCreateSchemaResponse
+ 73, // 102: pulsar.proto.BaseCommand.newTxn:type_name -> pulsar.proto.CommandNewTxn
+ 74, // 103: pulsar.proto.BaseCommand.newTxnResponse:type_name -> pulsar.proto.CommandNewTxnResponse
+ 75, // 104: pulsar.proto.BaseCommand.addPartitionToTxn:type_name -> pulsar.proto.CommandAddPartitionToTxn
+ 76, // 105: pulsar.proto.BaseCommand.addPartitionToTxnResponse:type_name -> pulsar.proto.CommandAddPartitionToTxnResponse
+ 78, // 106: pulsar.proto.BaseCommand.addSubscriptionToTxn:type_name -> pulsar.proto.CommandAddSubscriptionToTxn
+ 79, // 107: pulsar.proto.BaseCommand.addSubscriptionToTxnResponse:type_name -> pulsar.proto.CommandAddSubscriptionToTxnResponse
+ 80, // 108: pulsar.proto.BaseCommand.endTxn:type_name -> pulsar.proto.CommandEndTxn
+ 81, // 109: pulsar.proto.BaseCommand.endTxnResponse:type_name -> pulsar.proto.CommandEndTxnResponse
+ 82, // 110: pulsar.proto.BaseCommand.endTxnOnPartition:type_name -> pulsar.proto.CommandEndTxnOnPartition
+ 83, // 111: pulsar.proto.BaseCommand.endTxnOnPartitionResponse:type_name -> pulsar.proto.CommandEndTxnOnPartitionResponse
+ 84, // 112: pulsar.proto.BaseCommand.endTxnOnSubscription:type_name -> pulsar.proto.CommandEndTxnOnSubscription
+ 85, // 113: pulsar.proto.BaseCommand.endTxnOnSubscriptionResponse:type_name -> pulsar.proto.CommandEndTxnOnSubscriptionResponse
+ 71, // 114: pulsar.proto.BaseCommand.tcClientConnectRequest:type_name -> pulsar.proto.CommandTcClientConnectRequest
+ 72, // 115: pulsar.proto.BaseCommand.tcClientConnectResponse:type_name -> pulsar.proto.CommandTcClientConnectResponse
+ 63, // 116: pulsar.proto.BaseCommand.watchTopicList:type_name -> pulsar.proto.CommandWatchTopicList
+ 64, // 117: pulsar.proto.BaseCommand.watchTopicListSuccess:type_name -> pulsar.proto.CommandWatchTopicListSuccess
+ 65, // 118: pulsar.proto.BaseCommand.watchTopicUpdate:type_name -> pulsar.proto.CommandWatchTopicUpdate
+ 66, // 119: pulsar.proto.BaseCommand.watchTopicListClose:type_name -> pulsar.proto.CommandWatchTopicListClose
+ 120, // [120:120] is the sub-list for method output_type
+ 120, // [120:120] is the sub-list for method input_type
+ 120, // [120:120] is the sub-list for extension type_name
+ 120, // [120:120] is the sub-list for extension extendee
+ 0, // [0:120] is the sub-list for field type_name
+}
+
+func init() { file_PulsarApi_proto_init() }
+func file_PulsarApi_proto_init() {
+ if File_PulsarApi_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_PulsarApi_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Schema); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*MessageIdData); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*KeyValue); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*KeyLongValue); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*IntRange); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*EncryptionKeys); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*MessageMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SingleMessageMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*BrokerEntryMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandConnect); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FeatureFlags); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandConnected); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandAuthResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandAuthChallenge); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*AuthData); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*KeySharedMeta); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandSubscribe); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandPartitionedTopicMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandPartitionedTopicMetadataResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandLookupTopic); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandLookupTopicResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandProducer); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandSend); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandSendReceipt); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandSendError); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandMessage); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandAck); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandAckResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandActiveConsumerChange); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandFlow); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandUnsubscribe); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandSeek); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandReachedEndOfTopic); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandCloseProducer); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandCloseConsumer); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandRedeliverUnacknowledgedMessages); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandSuccess); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandProducerSuccess); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandError); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandPing); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandPong); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandConsumerStats); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandConsumerStatsResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandGetLastMessageId); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandGetLastMessageIdResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandGetTopicsOfNamespace); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandGetTopicsOfNamespaceResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandWatchTopicList); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandWatchTopicListSuccess); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandWatchTopicUpdate); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandWatchTopicListClose); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandGetSchema); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandGetSchemaResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandGetOrCreateSchema); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandGetOrCreateSchemaResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandTcClientConnectRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandTcClientConnectResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandNewTxn); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandNewTxnResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandAddPartitionToTxn); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandAddPartitionToTxnResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Subscription); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandAddSubscriptionToTxn); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandAddSubscriptionToTxnResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandEndTxn); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandEndTxnResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandEndTxnOnPartition); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandEndTxnOnPartitionResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandEndTxnOnSubscription); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CommandEndTxnOnSubscriptionResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_PulsarApi_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*BaseCommand); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_PulsarApi_proto_rawDesc,
+ NumEnums: 16,
+ NumMessages: 71,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_PulsarApi_proto_goTypes,
+ DependencyIndexes: file_PulsarApi_proto_depIdxs,
+ EnumInfos: file_PulsarApi_proto_enumTypes,
+ MessageInfos: file_PulsarApi_proto_msgTypes,
+ }.Build()
+ File_PulsarApi_proto = out.File
+ file_PulsarApi_proto_rawDesc = nil
+ file_PulsarApi_proto_goTypes = nil
+ file_PulsarApi_proto_depIdxs = nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/PulsarApi.proto b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/PulsarApi.proto
new file mode 100644
index 00000000..0c72361c
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/PulsarApi.proto
@@ -0,0 +1,1110 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+syntax = "proto2";
+
+package pulsar.proto;
+option java_package = "org.apache.pulsar.common.api.proto";
+option go_package = "./proto";
+option optimize_for = LITE_RUNTIME;
+
+message Schema {
+ enum Type {
+ None = 0;
+ String = 1;
+ Json = 2;
+ Protobuf = 3;
+ Avro = 4;
+ Bool = 5;
+ Int8 = 6;
+ Int16 = 7;
+ Int32 = 8;
+ Int64 = 9;
+ Float = 10;
+ Double = 11;
+ Date = 12;
+ Time = 13;
+ Timestamp = 14;
+ KeyValue = 15;
+ Instant = 16;
+ LocalDate = 17;
+ LocalTime = 18;
+ LocalDateTime = 19;
+ ProtobufNative = 20;
+ }
+
+ required string name = 1;
+ required bytes schema_data = 3;
+ required Type type = 4;
+ repeated KeyValue properties = 5;
+
+}
+
+message MessageIdData {
+ required uint64 ledgerId = 1;
+ required uint64 entryId = 2;
+ optional int32 partition = 3 [default = -1];
+ optional int32 batch_index = 4 [default = -1];
+ repeated int64 ack_set = 5;
+ optional int32 batch_size = 6;
+
+ // For the chunk message id, we need to specify the first chunk message id.
+ optional MessageIdData first_chunk_message_id = 7;
+}
+
+message KeyValue {
+ required string key = 1;
+ required string value = 2;
+}
+
+message KeyLongValue {
+ required string key = 1;
+ required uint64 value = 2;
+}
+
+message IntRange {
+ required int32 start = 1;
+ required int32 end = 2;
+}
+
+message EncryptionKeys {
+ required string key = 1;
+ required bytes value = 2;
+ repeated KeyValue metadata = 3;
+}
+
+enum CompressionType {
+ NONE = 0;
+ LZ4 = 1;
+ ZLIB = 2;
+ ZSTD = 3;
+ SNAPPY = 4;
+}
+
+enum ProducerAccessMode {
+ Shared = 0; // By default multiple producers can publish on a topic
+ Exclusive = 1; // Require exclusive access for producer. Fail immediately if there's already a producer connected.
+ WaitForExclusive = 2; // Producer creation is pending until it can acquire exclusive access
+ ExclusiveWithFencing = 3; // Require exclusive access for producer. Fence out old producer.
+}
+
+message MessageMetadata {
+ required string producer_name = 1;
+ required uint64 sequence_id = 2;
+ required uint64 publish_time = 3;
+ repeated KeyValue properties = 4;
+
+ // Property set on replicated message,
+ // includes the source cluster name
+ optional string replicated_from = 5;
+ //key to decide partition for the msg
+ optional string partition_key = 6;
+ // Override namespace's replication
+ repeated string replicate_to = 7;
+ optional CompressionType compression = 8 [default = NONE];
+ optional uint32 uncompressed_size = 9 [default = 0];
+ // Removed below checksum field from Metadata as
+ // it should be part of send-command which keeps checksum of header + payload
+ //optional sfixed64 checksum = 10;
+ // differentiate single and batch message metadata
+ optional int32 num_messages_in_batch = 11 [default = 1];
+
+ // the timestamp that this event occurs. it is typically set by applications.
+ // if this field is omitted, `publish_time` can be used for the purpose of `event_time`.
+ optional uint64 event_time = 12 [default = 0];
+ // Contains encryption key name, encrypted key and metadata to describe the key
+ repeated EncryptionKeys encryption_keys = 13;
+ // Algorithm used to encrypt data key
+ optional string encryption_algo = 14;
+ // Additional parameters required by encryption
+ optional bytes encryption_param = 15;
+ optional bytes schema_version = 16;
+
+ optional bool partition_key_b64_encoded = 17 [ default = false ];
+ // Specific a key to overwrite the message key which used for ordering dispatch in Key_Shared mode.
+ optional bytes ordering_key = 18;
+
+ // Mark the message to be delivered at or after the specified timestamp
+ optional int64 deliver_at_time = 19;
+
+ // Identify whether a message is a "marker" message used for
+ // internal metadata instead of application published data.
+ // Markers will generally not be propagated back to clients
+ optional int32 marker_type = 20;
+
+ // transaction related message info
+ optional uint64 txnid_least_bits = 22;
+ optional uint64 txnid_most_bits = 23;
+
+ /// Add highest sequence id to support batch message with external sequence id
+ optional uint64 highest_sequence_id = 24 [default = 0];
+
+ // Indicate if the message payload value is set
+ optional bool null_value = 25 [default = false];
+ optional string uuid = 26;
+ optional int32 num_chunks_from_msg = 27;
+ optional int32 total_chunk_msg_size = 28;
+ optional int32 chunk_id = 29;
+
+ // Indicate if the message partition key is set
+ optional bool null_partition_key = 30 [default = false];
+}
+
+message SingleMessageMetadata {
+ repeated KeyValue properties = 1;
+ optional string partition_key = 2;
+ required int32 payload_size = 3;
+ optional bool compacted_out = 4 [default = false];
+
+ // the timestamp that this event occurs. it is typically set by applications.
+ // if this field is omitted, `publish_time` can be used for the purpose of `event_time`.
+ optional uint64 event_time = 5 [default = 0];
+ optional bool partition_key_b64_encoded = 6 [ default = false ];
+ // Specific a key to overwrite the message key which used for ordering dispatch in Key_Shared mode.
+ optional bytes ordering_key = 7;
+ // Allows consumer retrieve the sequence id that the producer set.
+ optional uint64 sequence_id = 8;
+ // Indicate if the message payload value is set
+ optional bool null_value = 9 [ default = false ];
+ // Indicate if the message partition key is set
+ optional bool null_partition_key = 10 [ default = false];
+}
+
+// metadata added for entry from broker
+message BrokerEntryMetadata {
+ optional uint64 broker_timestamp = 1;
+ optional uint64 index = 2;
+}
+
+enum ServerError {
+ UnknownError = 0;
+ MetadataError = 1; // Error with ZK/metadata
+ PersistenceError = 2; // Error writing reading from BK
+ AuthenticationError = 3; // Non valid authentication
+ AuthorizationError = 4; // Not authorized to use resource
+
+ ConsumerBusy = 5; // Unable to subscribe/unsubscribe because
+ // other consumers are connected
+ ServiceNotReady = 6; // Any error that requires client retry operation with a fresh lookup
+ ProducerBlockedQuotaExceededError = 7; // Unable to create producer because backlog quota exceeded
+ ProducerBlockedQuotaExceededException = 8; // Exception while creating producer because quota exceeded
+ ChecksumError = 9; // Error while verifying message checksum
+ UnsupportedVersionError = 10; // Error when an older client/version doesn't support a required feature
+ TopicNotFound = 11; // Topic not found
+ SubscriptionNotFound = 12; // Subscription not found
+ ConsumerNotFound = 13; // Consumer not found
+ TooManyRequests = 14; // Error with too many simultaneously request
+ TopicTerminatedError = 15; // The topic has been terminated
+
+ ProducerBusy = 16; // Producer with same name is already connected
+ InvalidTopicName = 17; // The topic name is not valid
+
+ IncompatibleSchema = 18; // Specified schema was incompatible with topic schema
+ ConsumerAssignError = 19; // Dispatcher assign consumer error
+
+ TransactionCoordinatorNotFound = 20; // Transaction coordinator not found error
+ InvalidTxnStatus = 21; // Invalid txn status error
+ NotAllowedError = 22; // Not allowed error
+
+ TransactionConflict = 23; // Ack with transaction conflict
+ TransactionNotFound = 24; // Transaction not found
+
+ ProducerFenced = 25; // When a producer asks and fail to get exclusive producer access,
+ // or loses the eclusive status after a reconnection, the broker will
+ // use this error to indicate that this producer is now permanently
+ // fenced. Applications are now supposed to close it and create a
+ // new producer
+}
+
+enum AuthMethod {
+ AuthMethodNone = 0;
+ AuthMethodYcaV1 = 1;
+ AuthMethodAthens = 2;
+}
+
+// Each protocol version identify new features that are
+// incrementally added to the protocol
+enum ProtocolVersion {
+ v0 = 0; // Initial versioning
+ v1 = 1; // Added application keep-alive
+ v2 = 2; // Added RedeliverUnacknowledgedMessages Command
+ v3 = 3; // Added compression with LZ4 and ZLib
+ v4 = 4; // Added batch message support
+ v5 = 5; // Added disconnect client w/o closing connection
+ v6 = 6; // Added checksum computation for metadata + payload
+ v7 = 7; // Added CommandLookupTopic - Binary Lookup
+ v8 = 8; // Added CommandConsumerStats - Client fetches broker side consumer stats
+ v9 = 9; // Added end of topic notification
+ v10 = 10;// Added proxy to broker
+ v11 = 11;// C++ consumers before this version are not correctly handling the checksum field
+ v12 = 12;// Added get topic's last messageId from broker
+ // Added CommandActiveConsumerChange
+ // Added CommandGetTopicsOfNamespace
+ v13 = 13; // Schema-registry : added avro schema format for json
+ v14 = 14; // Add CommandAuthChallenge and CommandAuthResponse for mutual auth
+ // Added Key_Shared subscription
+ v15 = 15; // Add CommandGetOrCreateSchema and CommandGetOrCreateSchemaResponse
+ v16 = 16; // Add support for broker entry metadata
+ v17 = 17; // Added support ack receipt
+ v18 = 18; // Add client support for broker entry metadata
+ v19 = 19; // Add CommandTcClientConnectRequest and CommandTcClientConnectResponse
+}
+
+message CommandConnect {
+ required string client_version = 1;
+ optional AuthMethod auth_method = 2; // Deprecated. Use "auth_method_name" instead.
+ optional string auth_method_name = 5;
+ optional bytes auth_data = 3;
+ optional int32 protocol_version = 4 [default = 0];
+
+ // Client can ask to be proxyied to a specific broker
+ // This is only honored by a Pulsar proxy
+ optional string proxy_to_broker_url = 6;
+
+ // Original principal that was verified by
+ // a Pulsar proxy. In this case the auth info above
+ // will be the auth of the proxy itself
+ optional string original_principal = 7;
+
+ // Original auth role and auth Method that was passed
+ // to the proxy. In this case the auth info above
+ // will be the auth of the proxy itself
+ optional string original_auth_data = 8;
+ optional string original_auth_method = 9;
+
+ // Feature flags
+ optional FeatureFlags feature_flags = 10;
+}
+
+message FeatureFlags {
+ optional bool supports_auth_refresh = 1 [default = false];
+ optional bool supports_broker_entry_metadata = 2 [default = false];
+ optional bool supports_partial_producer = 3 [default = false];
+ optional bool supports_topic_watchers = 4 [default = false];
+}
+
+message CommandConnected {
+ required string server_version = 1;
+ optional int32 protocol_version = 2 [default = 0];
+ optional int32 max_message_size = 3;
+ optional FeatureFlags feature_flags = 4;
+}
+
+message CommandAuthResponse {
+ optional string client_version = 1;
+ optional AuthData response = 2;
+ optional int32 protocol_version = 3 [default = 0];
+}
+
+message CommandAuthChallenge {
+ optional string server_version = 1;
+ optional AuthData challenge = 2;
+ optional int32 protocol_version = 3 [default = 0];
+}
+
+// To support mutual authentication type, such as Sasl, reuse this command to mutual auth.
+message AuthData {
+ optional string auth_method_name = 1;
+ optional bytes auth_data = 2;
+}
+
+enum KeySharedMode {
+ AUTO_SPLIT = 0;
+ STICKY = 1;
+}
+
+message KeySharedMeta {
+ required KeySharedMode keySharedMode = 1;
+ repeated IntRange hashRanges = 3;
+ optional bool allowOutOfOrderDelivery = 4 [default = false];
+}
+
+message CommandSubscribe {
+ enum SubType {
+ Exclusive = 0;
+ Shared = 1;
+ Failover = 2;
+ Key_Shared = 3;
+ }
+ required string topic = 1;
+ required string subscription = 2;
+ required SubType subType = 3;
+
+ required uint64 consumer_id = 4;
+ required uint64 request_id = 5;
+ optional string consumer_name = 6;
+ optional int32 priority_level = 7;
+
+ // Signal wether the subscription should be backed by a
+ // durable cursor or not
+ optional bool durable = 8 [default = true];
+
+ // If specified, the subscription will position the cursor
+ // markd-delete position on the particular message id and
+ // will send messages from that point
+ optional MessageIdData start_message_id = 9;
+
+ /// Add optional metadata key=value to this consumer
+ repeated KeyValue metadata = 10;
+
+ optional bool read_compacted = 11;
+
+ optional Schema schema = 12;
+ enum InitialPosition {
+ Latest = 0;
+ Earliest = 1;
+ }
+ // Signal whether the subscription will initialize on latest
+ // or not -- earliest
+ optional InitialPosition initialPosition = 13 [default = Latest];
+
+ // Mark the subscription as "replicated". Pulsar will make sure
+ // to periodically sync the state of replicated subscriptions
+ // across different clusters (when using geo-replication).
+ optional bool replicate_subscription_state = 14;
+
+ // If true, the subscribe operation will cause a topic to be
+ // created if it does not exist already (and if topic auto-creation
+ // is allowed by broker.
+ // If false, the subscribe operation will fail if the topic
+ // does not exist.
+ optional bool force_topic_creation = 15 [default = true];
+
+ // If specified, the subscription will reset cursor's position back
+ // to specified seconds and will send messages from that point
+ optional uint64 start_message_rollback_duration_sec = 16 [default = 0];
+
+ optional KeySharedMeta keySharedMeta = 17;
+
+ repeated KeyValue subscription_properties = 18;
+
+ // The consumer epoch, when exclusive and failover consumer redeliver unack message will increase the epoch
+ optional uint64 consumer_epoch = 19;
+}
+
+message CommandPartitionedTopicMetadata {
+ required string topic = 1;
+ required uint64 request_id = 2;
+ // TODO - Remove original_principal, original_auth_data, original_auth_method
+ // Original principal that was verified by
+ // a Pulsar proxy.
+ optional string original_principal = 3;
+
+ // Original auth role and auth Method that was passed
+ // to the proxy.
+ optional string original_auth_data = 4;
+ optional string original_auth_method = 5;
+}
+
+message CommandPartitionedTopicMetadataResponse {
+ enum LookupType {
+ Success = 0;
+ Failed = 1;
+ }
+ optional uint32 partitions = 1; // Optional in case of error
+ required uint64 request_id = 2;
+ optional LookupType response = 3;
+ optional ServerError error = 4;
+ optional string message = 5;
+}
+
+message CommandLookupTopic {
+ required string topic = 1;
+ required uint64 request_id = 2;
+ optional bool authoritative = 3 [default = false];
+
+ // TODO - Remove original_principal, original_auth_data, original_auth_method
+ // Original principal that was verified by
+ // a Pulsar proxy.
+ optional string original_principal = 4;
+
+ // Original auth role and auth Method that was passed
+ // to the proxy.
+ optional string original_auth_data = 5;
+ optional string original_auth_method = 6;
+ //
+ optional string advertised_listener_name = 7;
+}
+
+message CommandLookupTopicResponse {
+ enum LookupType {
+ Redirect = 0;
+ Connect = 1;
+ Failed = 2;
+ }
+
+ optional string brokerServiceUrl = 1; // Optional in case of error
+ optional string brokerServiceUrlTls = 2;
+ optional LookupType response = 3;
+ required uint64 request_id = 4;
+ optional bool authoritative = 5 [default = false];
+ optional ServerError error = 6;
+ optional string message = 7;
+
+ // If it's true, indicates to the client that it must
+ // always connect through the service url after the
+ // lookup has been completed.
+ optional bool proxy_through_service_url = 8 [default = false];
+}
+
+/// Create a new Producer on a topic, assigning the given producer_id,
+/// all messages sent with this producer_id will be persisted on the topic
+message CommandProducer {
+ required string topic = 1;
+ required uint64 producer_id = 2;
+ required uint64 request_id = 3;
+
+ /// If a producer name is specified, the name will be used,
+ /// otherwise the broker will generate a unique name
+ optional string producer_name = 4;
+
+ optional bool encrypted = 5 [default = false];
+
+ /// Add optional metadata key=value to this producer
+ repeated KeyValue metadata = 6;
+
+ optional Schema schema = 7;
+
+ // If producer reconnect to broker, the epoch of this producer will +1
+ optional uint64 epoch = 8 [default = 0];
+
+ // Indicate the name of the producer is generated or user provided
+ // Use default true here is in order to be forward compatible with the client
+ optional bool user_provided_producer_name = 9 [default = true];
+
+ // Require that this producers will be the only producer allowed on the topic
+ optional ProducerAccessMode producer_access_mode = 10 [default = Shared];
+
+ // Topic epoch is used to fence off producers that reconnects after a new
+ // exclusive producer has already taken over. This id is assigned by the
+ // broker on the CommandProducerSuccess. The first time, the client will
+ // leave it empty and then it will always carry the same epoch number on
+ // the subsequent reconnections.
+ optional uint64 topic_epoch = 11;
+
+ optional bool txn_enabled = 12 [default = false];
+
+ // Name of the initial subscription of the topic.
+ // If this field is not set, the initial subscription will not be created.
+ // If this field is set but the broker's `allowAutoSubscriptionCreation`
+ // is disabled, the producer will fail to be created.
+ optional string initial_subscription_name = 13;
+}
+
+message CommandSend {
+ required uint64 producer_id = 1;
+ required uint64 sequence_id = 2;
+ optional int32 num_messages = 3 [default = 1];
+ optional uint64 txnid_least_bits = 4 [default = 0];
+ optional uint64 txnid_most_bits = 5 [default = 0];
+
+ /// Add highest sequence id to support batch message with external sequence id
+ optional uint64 highest_sequence_id = 6 [default = 0];
+ optional bool is_chunk =7 [default = false];
+
+ // Specify if the message being published is a Pulsar marker or not
+ optional bool marker = 8 [default = false];
+
+ // Message id of this message, currently is used in replicator for shadow topic.
+ optional MessageIdData message_id = 9;
+}
+
+message CommandSendReceipt {
+ required uint64 producer_id = 1;
+ required uint64 sequence_id = 2;
+ optional MessageIdData message_id = 3;
+ optional uint64 highest_sequence_id = 4 [default = 0];
+}
+
+message CommandSendError {
+ required uint64 producer_id = 1;
+ required uint64 sequence_id = 2;
+ required ServerError error = 3;
+ required string message = 4;
+}
+
+message CommandMessage {
+ required uint64 consumer_id = 1;
+ required MessageIdData message_id = 2;
+ optional uint32 redelivery_count = 3 [default = 0];
+ repeated int64 ack_set = 4;
+ optional uint64 consumer_epoch = 5;
+}
+
+message CommandAck {
+ enum AckType {
+ Individual = 0;
+ Cumulative = 1;
+ }
+
+ required uint64 consumer_id = 1;
+ required AckType ack_type = 2;
+
+ // In case of individual acks, the client can pass a list of message ids
+ repeated MessageIdData message_id = 3;
+
+ // Acks can contain a flag to indicate the consumer
+ // received an invalid message that got discarded
+ // before being passed on to the application.
+ enum ValidationError {
+ UncompressedSizeCorruption = 0;
+ DecompressionError = 1;
+ ChecksumMismatch = 2;
+ BatchDeSerializeError = 3;
+ DecryptionError = 4;
+ }
+
+ optional ValidationError validation_error = 4;
+ repeated KeyLongValue properties = 5;
+
+ optional uint64 txnid_least_bits = 6 [default = 0];
+ optional uint64 txnid_most_bits = 7 [default = 0];
+ optional uint64 request_id = 8;
+}
+
+message CommandAckResponse {
+ required uint64 consumer_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional ServerError error = 4;
+ optional string message = 5;
+ optional uint64 request_id = 6;
+}
+
+// changes on active consumer
+message CommandActiveConsumerChange {
+ required uint64 consumer_id = 1;
+ optional bool is_active = 2 [default = false];
+}
+
+message CommandFlow {
+ required uint64 consumer_id = 1;
+
+ // Max number of messages to prefetch, in addition
+ // of any number previously specified
+ required uint32 messagePermits = 2;
+}
+
+message CommandUnsubscribe {
+ required uint64 consumer_id = 1;
+ required uint64 request_id = 2;
+}
+
+// Reset an existing consumer to a particular message id
+message CommandSeek {
+ required uint64 consumer_id = 1;
+ required uint64 request_id = 2;
+
+ optional MessageIdData message_id = 3;
+ optional uint64 message_publish_time = 4;
+}
+
+// Message sent by broker to client when a topic
+// has been forcefully terminated and there are no more
+// messages left to consume
+message CommandReachedEndOfTopic {
+ required uint64 consumer_id = 1;
+}
+
+message CommandCloseProducer {
+ required uint64 producer_id = 1;
+ required uint64 request_id = 2;
+}
+
+message CommandCloseConsumer {
+ required uint64 consumer_id = 1;
+ required uint64 request_id = 2;
+}
+
+message CommandRedeliverUnacknowledgedMessages {
+ required uint64 consumer_id = 1;
+ repeated MessageIdData message_ids = 2;
+ optional uint64 consumer_epoch = 3;
+}
+
+message CommandSuccess {
+ required uint64 request_id = 1;
+ optional Schema schema = 2;
+}
+
+/// Response from CommandProducer
+message CommandProducerSuccess {
+ required uint64 request_id = 1;
+ required string producer_name = 2;
+
+ // The last sequence id that was stored by this producer in the previous session
+ // This will only be meaningful if deduplication has been enabled.
+ optional int64 last_sequence_id = 3 [default = -1];
+ optional bytes schema_version = 4;
+
+ // The topic epoch assigned by the broker. This field will only be set if we
+ // were requiring exclusive access when creating the producer.
+ optional uint64 topic_epoch = 5;
+
+ // If producer is not "ready", the client will avoid to timeout the request
+ // for creating the producer. Instead it will wait indefinitely until it gets
+ // a subsequent `CommandProducerSuccess` with `producer_ready==true`.
+ optional bool producer_ready = 6 [default = true];
+}
+
+message CommandError {
+ required uint64 request_id = 1;
+ required ServerError error = 2;
+ required string message = 3;
+}
+
+// Commands to probe the state of connection.
+// When either client or broker doesn't receive commands for certain
+// amount of time, they will send a Ping probe.
+message CommandPing {
+}
+message CommandPong {
+}
+
+message CommandConsumerStats {
+ required uint64 request_id = 1;
+ // required string topic_name = 2;
+ // required string subscription_name = 3;
+ required uint64 consumer_id = 4;
+}
+
+message CommandConsumerStatsResponse {
+ required uint64 request_id = 1;
+ optional ServerError error_code = 2;
+ optional string error_message = 3;
+
+ /// Total rate of messages delivered to the consumer. msg/s
+ optional double msgRateOut = 4;
+
+ /// Total throughput delivered to the consumer. bytes/s
+ optional double msgThroughputOut = 5;
+
+ /// Total rate of messages redelivered by this consumer. msg/s
+ optional double msgRateRedeliver = 6;
+
+ /// Name of the consumer
+ optional string consumerName = 7;
+
+ /// Number of available message permits for the consumer
+ optional uint64 availablePermits = 8;
+
+ /// Number of unacknowledged messages for the consumer
+ optional uint64 unackedMessages = 9;
+
+ /// Flag to verify if consumer is blocked due to reaching threshold of unacked messages
+ optional bool blockedConsumerOnUnackedMsgs = 10;
+
+ /// Address of this consumer
+ optional string address = 11;
+
+ /// Timestamp of connection
+ optional string connectedSince = 12;
+
+ /// Whether this subscription is Exclusive or Shared or Failover
+ optional string type = 13;
+
+ /// Total rate of messages expired on this subscription. msg/s
+ optional double msgRateExpired = 14;
+
+ /// Number of messages in the subscription backlog
+ optional uint64 msgBacklog = 15;
+
+ /// Total rate of messages ack. msg/s
+ optional double messageAckRate = 16;
+}
+
+message CommandGetLastMessageId {
+ required uint64 consumer_id = 1;
+ required uint64 request_id = 2;
+}
+
+message CommandGetLastMessageIdResponse {
+ required MessageIdData last_message_id = 1;
+ required uint64 request_id = 2;
+ optional MessageIdData consumer_mark_delete_position = 3;
+}
+
+message CommandGetTopicsOfNamespace {
+ enum Mode {
+ PERSISTENT = 0;
+ NON_PERSISTENT = 1;
+ ALL = 2;
+ }
+ required uint64 request_id = 1;
+ required string namespace = 2;
+ optional Mode mode = 3 [default = PERSISTENT];
+ optional string topics_pattern = 4;
+ optional string topics_hash = 5;
+}
+
+message CommandGetTopicsOfNamespaceResponse {
+ required uint64 request_id = 1;
+ repeated string topics = 2;
+ // true iff the topic list was filtered by the pattern supplied by the client
+ optional bool filtered = 3 [default = false];
+ // hash computed from the names of matching topics
+ optional string topics_hash = 4;
+ // if false, topics is empty and the list of matching topics has not changed
+ optional bool changed = 5 [default = true];
+}
+
+message CommandWatchTopicList {
+ required uint64 request_id = 1;
+ required uint64 watcher_id = 2;
+ required string namespace = 3;
+ required string topics_pattern = 4;
+ // Only present when the client reconnects:
+ optional string topics_hash = 5;
+}
+
+message CommandWatchTopicListSuccess {
+ required uint64 request_id = 1;
+ required uint64 watcher_id = 2;
+ repeated string topic = 3;
+ required string topics_hash = 4;
+}
+
+message CommandWatchTopicUpdate {
+ required uint64 watcher_id = 1;
+ repeated string new_topics = 2;
+ repeated string deleted_topics = 3;
+ required string topics_hash = 4;
+}
+
+message CommandWatchTopicListClose {
+ required uint64 request_id = 1;
+ required uint64 watcher_id = 2;
+}
+
+message CommandGetSchema {
+ required uint64 request_id = 1;
+ required string topic = 2;
+
+ optional bytes schema_version = 3;
+}
+
+message CommandGetSchemaResponse {
+ required uint64 request_id = 1;
+ optional ServerError error_code = 2;
+ optional string error_message = 3;
+
+ optional Schema schema = 4;
+ optional bytes schema_version = 5;
+}
+
+message CommandGetOrCreateSchema {
+ required uint64 request_id = 1;
+ required string topic = 2;
+ required Schema schema = 3;
+}
+
+message CommandGetOrCreateSchemaResponse {
+ required uint64 request_id = 1;
+ optional ServerError error_code = 2;
+ optional string error_message = 3;
+
+ optional bytes schema_version = 4;
+}
+
+/// --- transaction related ---
+
+enum TxnAction {
+ COMMIT = 0;
+ ABORT = 1;
+}
+
+message CommandTcClientConnectRequest {
+ required uint64 request_id = 1;
+ required uint64 tc_id = 2 [default = 0];
+}
+
+message CommandTcClientConnectResponse {
+ required uint64 request_id = 1;
+ optional ServerError error = 2;
+ optional string message = 3;
+}
+
+message CommandNewTxn {
+ required uint64 request_id = 1;
+ optional uint64 txn_ttl_seconds = 2 [default = 0];
+ optional uint64 tc_id = 3 [default = 0];
+}
+
+message CommandNewTxnResponse {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional ServerError error = 4;
+ optional string message = 5;
+}
+
+message CommandAddPartitionToTxn {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ repeated string partitions = 4;
+}
+
+message CommandAddPartitionToTxnResponse {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional ServerError error = 4;
+ optional string message = 5;
+}
+
+message Subscription {
+ required string topic = 1;
+ required string subscription = 2;
+}
+message CommandAddSubscriptionToTxn {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ repeated Subscription subscription = 4;
+}
+
+message CommandAddSubscriptionToTxnResponse {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional ServerError error = 4;
+ optional string message = 5;
+}
+
+message CommandEndTxn {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional TxnAction txn_action = 4;
+}
+
+message CommandEndTxnResponse {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional ServerError error = 4;
+ optional string message = 5;
+}
+
+message CommandEndTxnOnPartition {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional string topic = 4;
+ optional TxnAction txn_action = 5;
+ optional uint64 txnid_least_bits_of_low_watermark = 6;
+}
+
+message CommandEndTxnOnPartitionResponse {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional ServerError error = 4;
+ optional string message = 5;
+}
+
+message CommandEndTxnOnSubscription {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional Subscription subscription= 4;
+ optional TxnAction txn_action = 5;
+ optional uint64 txnid_least_bits_of_low_watermark = 6;
+}
+
+message CommandEndTxnOnSubscriptionResponse {
+ required uint64 request_id = 1;
+ optional uint64 txnid_least_bits = 2 [default = 0];
+ optional uint64 txnid_most_bits = 3 [default = 0];
+ optional ServerError error = 4;
+ optional string message = 5;
+}
+
+message BaseCommand {
+ enum Type {
+ CONNECT = 2;
+ CONNECTED = 3;
+ SUBSCRIBE = 4;
+
+ PRODUCER = 5;
+
+ SEND = 6;
+ SEND_RECEIPT= 7;
+ SEND_ERROR = 8;
+
+ MESSAGE = 9;
+ ACK = 10;
+ FLOW = 11;
+
+ UNSUBSCRIBE = 12;
+
+ SUCCESS = 13;
+ ERROR = 14;
+
+ CLOSE_PRODUCER = 15;
+ CLOSE_CONSUMER = 16;
+
+ PRODUCER_SUCCESS = 17;
+
+ PING = 18;
+ PONG = 19;
+
+ REDELIVER_UNACKNOWLEDGED_MESSAGES = 20;
+
+ PARTITIONED_METADATA = 21;
+ PARTITIONED_METADATA_RESPONSE = 22;
+
+ LOOKUP = 23;
+ LOOKUP_RESPONSE = 24;
+
+ CONSUMER_STATS = 25;
+ CONSUMER_STATS_RESPONSE = 26;
+
+ REACHED_END_OF_TOPIC = 27;
+
+ SEEK = 28;
+
+ GET_LAST_MESSAGE_ID = 29;
+ GET_LAST_MESSAGE_ID_RESPONSE = 30;
+
+ ACTIVE_CONSUMER_CHANGE = 31;
+
+
+ GET_TOPICS_OF_NAMESPACE = 32;
+ GET_TOPICS_OF_NAMESPACE_RESPONSE = 33;
+
+ GET_SCHEMA = 34;
+ GET_SCHEMA_RESPONSE = 35;
+
+ AUTH_CHALLENGE = 36;
+ AUTH_RESPONSE = 37;
+
+ ACK_RESPONSE = 38;
+
+ GET_OR_CREATE_SCHEMA = 39;
+ GET_OR_CREATE_SCHEMA_RESPONSE = 40;
+
+ // transaction related
+ NEW_TXN = 50;
+ NEW_TXN_RESPONSE = 51;
+
+ ADD_PARTITION_TO_TXN = 52;
+ ADD_PARTITION_TO_TXN_RESPONSE = 53;
+
+ ADD_SUBSCRIPTION_TO_TXN = 54;
+ ADD_SUBSCRIPTION_TO_TXN_RESPONSE = 55;
+
+ END_TXN = 56;
+ END_TXN_RESPONSE = 57;
+
+ END_TXN_ON_PARTITION = 58;
+ END_TXN_ON_PARTITION_RESPONSE = 59;
+
+ END_TXN_ON_SUBSCRIPTION = 60;
+ END_TXN_ON_SUBSCRIPTION_RESPONSE = 61;
+ TC_CLIENT_CONNECT_REQUEST = 62;
+ TC_CLIENT_CONNECT_RESPONSE = 63;
+
+ WATCH_TOPIC_LIST = 64;
+ WATCH_TOPIC_LIST_SUCCESS = 65;
+ WATCH_TOPIC_UPDATE = 66;
+ WATCH_TOPIC_LIST_CLOSE = 67;
+
+ }
+
+
+ required Type type = 1;
+
+ optional CommandConnect connect = 2;
+ optional CommandConnected connected = 3;
+
+ optional CommandSubscribe subscribe = 4;
+ optional CommandProducer producer = 5;
+ optional CommandSend send = 6;
+ optional CommandSendReceipt send_receipt = 7;
+ optional CommandSendError send_error = 8;
+ optional CommandMessage message = 9;
+ optional CommandAck ack = 10;
+ optional CommandFlow flow = 11;
+ optional CommandUnsubscribe unsubscribe = 12;
+
+ optional CommandSuccess success = 13;
+ optional CommandError error = 14;
+
+ optional CommandCloseProducer close_producer = 15;
+ optional CommandCloseConsumer close_consumer = 16;
+
+ optional CommandProducerSuccess producer_success = 17;
+ optional CommandPing ping = 18;
+ optional CommandPong pong = 19;
+ optional CommandRedeliverUnacknowledgedMessages redeliverUnacknowledgedMessages = 20;
+
+ optional CommandPartitionedTopicMetadata partitionMetadata = 21;
+ optional CommandPartitionedTopicMetadataResponse partitionMetadataResponse = 22;
+
+ optional CommandLookupTopic lookupTopic = 23;
+ optional CommandLookupTopicResponse lookupTopicResponse = 24;
+
+ optional CommandConsumerStats consumerStats = 25;
+ optional CommandConsumerStatsResponse consumerStatsResponse = 26;
+
+ optional CommandReachedEndOfTopic reachedEndOfTopic = 27;
+
+ optional CommandSeek seek = 28;
+
+ optional CommandGetLastMessageId getLastMessageId = 29;
+ optional CommandGetLastMessageIdResponse getLastMessageIdResponse = 30;
+
+ optional CommandActiveConsumerChange active_consumer_change = 31;
+
+ optional CommandGetTopicsOfNamespace getTopicsOfNamespace = 32;
+ optional CommandGetTopicsOfNamespaceResponse getTopicsOfNamespaceResponse = 33;
+
+ optional CommandGetSchema getSchema = 34;
+ optional CommandGetSchemaResponse getSchemaResponse = 35;
+
+ optional CommandAuthChallenge authChallenge = 36;
+ optional CommandAuthResponse authResponse = 37;
+
+ optional CommandAckResponse ackResponse = 38;
+
+ optional CommandGetOrCreateSchema getOrCreateSchema = 39;
+ optional CommandGetOrCreateSchemaResponse getOrCreateSchemaResponse = 40;
+
+ // transaction related
+ optional CommandNewTxn newTxn = 50;
+ optional CommandNewTxnResponse newTxnResponse = 51;
+ optional CommandAddPartitionToTxn addPartitionToTxn= 52;
+ optional CommandAddPartitionToTxnResponse addPartitionToTxnResponse = 53;
+ optional CommandAddSubscriptionToTxn addSubscriptionToTxn = 54;
+ optional CommandAddSubscriptionToTxnResponse addSubscriptionToTxnResponse = 55;
+ optional CommandEndTxn endTxn = 56;
+ optional CommandEndTxnResponse endTxnResponse = 57;
+ optional CommandEndTxnOnPartition endTxnOnPartition = 58;
+ optional CommandEndTxnOnPartitionResponse endTxnOnPartitionResponse = 59;
+ optional CommandEndTxnOnSubscription endTxnOnSubscription = 60;
+ optional CommandEndTxnOnSubscriptionResponse endTxnOnSubscriptionResponse = 61;
+ optional CommandTcClientConnectRequest tcClientConnectRequest = 62;
+ optional CommandTcClientConnectResponse tcClientConnectResponse = 63;
+
+ optional CommandWatchTopicList watchTopicList = 64;
+ optional CommandWatchTopicListSuccess watchTopicListSuccess = 65;
+ optional CommandWatchTopicUpdate watchTopicUpdate = 66;
+ optional CommandWatchTopicListClose watchTopicListClose = 67;
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/README.md b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/README.md
new file mode 100644
index 00000000..0ca933f4
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto/README.md
@@ -0,0 +1,11 @@
+protoc-gen-go:
+
+```shell
+go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
+```
+
+Generate code:
+
+```shell
+protoc --go_out=. --go_opt=paths=source_relative PulsarApi.proto
+```
\ No newline at end of file
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/rpc_client.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/rpc_client.go
new file mode 100644
index 00000000..2213083d
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/rpc_client.go
@@ -0,0 +1,190 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "errors"
+ "net/url"
+ "sync/atomic"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/log"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "google.golang.org/protobuf/proto"
+)
+
+var (
+ // ErrRequestTimeOut happens when request not finished in given requestTimeout.
+ ErrRequestTimeOut = errors.New("request timed out")
+)
+
+type result struct {
+ *RPCResult
+ error
+}
+
+type RPCResult struct {
+ Response *pb.BaseCommand
+ Cnx Connection
+}
+
+type RPCClient interface {
+ // Create a new unique request id
+ NewRequestID() uint64
+
+ NewProducerID() uint64
+
+ NewConsumerID() uint64
+
+ // Send a request and block until the result is available
+ RequestToAnyBroker(requestID uint64, cmdType pb.BaseCommand_Type, message proto.Message) (*RPCResult, error)
+
+ Request(logicalAddr *url.URL, physicalAddr *url.URL, requestID uint64,
+ cmdType pb.BaseCommand_Type, message proto.Message) (*RPCResult, error)
+
+ RequestOnCnxNoWait(cnx Connection, cmdType pb.BaseCommand_Type, message proto.Message) error
+
+ RequestOnCnx(cnx Connection, requestID uint64, cmdType pb.BaseCommand_Type, message proto.Message) (*RPCResult, error)
+}
+
+type rpcClient struct {
+ serviceNameResolver ServiceNameResolver
+ pool ConnectionPool
+ requestTimeout time.Duration
+ requestIDGenerator uint64
+ producerIDGenerator uint64
+ consumerIDGenerator uint64
+ log log.Logger
+ metrics *Metrics
+}
+
+func NewRPCClient(serviceURL *url.URL, serviceNameResolver ServiceNameResolver, pool ConnectionPool,
+ requestTimeout time.Duration, logger log.Logger, metrics *Metrics) RPCClient {
+ return &rpcClient{
+ serviceNameResolver: serviceNameResolver,
+ pool: pool,
+ requestTimeout: requestTimeout,
+ log: logger.SubLogger(log.Fields{"serviceURL": serviceURL}),
+ metrics: metrics,
+ }
+}
+
+func (c *rpcClient) RequestToAnyBroker(requestID uint64, cmdType pb.BaseCommand_Type,
+ message proto.Message) (*RPCResult, error) {
+ var err error
+ var host *url.URL
+ var rpcResult *RPCResult
+ startTime := time.Now()
+ backoff := DefaultBackoff{100 * time.Millisecond}
+ // we can retry these requests because this kind of request is
+ // not specific to any particular broker
+ for time.Since(startTime) < c.requestTimeout {
+ host, err = c.serviceNameResolver.ResolveHost()
+ if err != nil {
+ c.log.WithError(err).Errorf("rpc client failed to resolve host")
+ return nil, err
+ }
+ rpcResult, err = c.Request(host, host, requestID, cmdType, message)
+ // success we got a response
+ if err == nil {
+ break
+ }
+
+ retryTime := backoff.Next()
+ c.log.Debugf("Retrying request in {%v} with timeout in {%v}", retryTime, c.requestTimeout)
+ time.Sleep(retryTime)
+ }
+
+ return rpcResult, err
+}
+
+func (c *rpcClient) Request(logicalAddr *url.URL, physicalAddr *url.URL, requestID uint64,
+ cmdType pb.BaseCommand_Type, message proto.Message) (*RPCResult, error) {
+ c.metrics.RPCRequestCount.Inc()
+ cnx, err := c.pool.GetConnection(logicalAddr, physicalAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ ch := make(chan result, 1)
+
+ cnx.SendRequest(requestID, baseCommand(cmdType, message), func(response *pb.BaseCommand, err error) {
+ ch <- result{&RPCResult{
+ Cnx: cnx,
+ Response: response,
+ }, err}
+ })
+
+ timeoutCh := time.After(c.requestTimeout)
+ for {
+ select {
+ case res := <-ch:
+ // Ignoring producer not ready response.
+ // Continue to wait for the producer to create successfully
+ if res.error == nil && *res.RPCResult.Response.Type == pb.BaseCommand_PRODUCER_SUCCESS {
+ if !res.RPCResult.Response.ProducerSuccess.GetProducerReady() {
+ timeoutCh = nil
+ break
+ }
+ }
+ return res.RPCResult, res.error
+ case <-timeoutCh:
+ return nil, ErrRequestTimeOut
+ }
+ }
+}
+
+func (c *rpcClient) RequestOnCnx(cnx Connection, requestID uint64, cmdType pb.BaseCommand_Type,
+ message proto.Message) (*RPCResult, error) {
+ c.metrics.RPCRequestCount.Inc()
+
+ ch := make(chan result, 1)
+
+ cnx.SendRequest(requestID, baseCommand(cmdType, message), func(response *pb.BaseCommand, err error) {
+ ch <- result{&RPCResult{
+ Cnx: cnx,
+ Response: response,
+ }, err}
+ close(ch)
+ })
+
+ select {
+ case res := <-ch:
+ return res.RPCResult, res.error
+ case <-time.After(c.requestTimeout):
+ return nil, ErrRequestTimeOut
+ }
+}
+
+func (c *rpcClient) RequestOnCnxNoWait(cnx Connection, cmdType pb.BaseCommand_Type, message proto.Message) error {
+ c.metrics.RPCRequestCount.Inc()
+ return cnx.SendRequestNoWait(baseCommand(cmdType, message))
+}
+
+func (c *rpcClient) NewRequestID() uint64 {
+ return atomic.AddUint64(&c.requestIDGenerator, 1)
+}
+
+func (c *rpcClient) NewProducerID() uint64 {
+ return atomic.AddUint64(&c.producerIDGenerator, 1)
+}
+
+func (c *rpcClient) NewConsumerID() uint64 {
+ return atomic.AddUint64(&c.consumerIDGenerator, 1)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/semaphore.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/semaphore.go
new file mode 100644
index 00000000..6a67cc35
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/semaphore.go
@@ -0,0 +1,105 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "context"
+ "sync/atomic"
+
+ log "github.com/sirupsen/logrus"
+)
+
+type Semaphore interface {
+ // Acquire a permit, if one is available and returns immediately,
+ // reducing the number of available permits by one.
+ Acquire(ctx context.Context) bool
+
+ // Try to acquire a permit. The method will return immediately
+ // with a `true` if it was possible to acquire a permit and
+ // `false` otherwise.
+ TryAcquire() bool
+
+ // Release a permit, returning it to the semaphore.
+ // Release a permit, increasing the number of available permits by
+ // one. If any threads are trying to acquire a permit, then one is
+ // selected and given the permit that was just released. That thread
+ // is (re)enabled for thread scheduling purposes.
+ // There is no requirement that a thread that releases a permit must
+ // have acquired that permit by calling Acquire().
+ // Correct usage of a semaphore is established by programming convention
+ // in the application.
+ Release()
+}
+
+type semaphore struct {
+ maxPermits int32
+ permits int32
+ ch chan bool
+}
+
+func NewSemaphore(maxPermits int32) Semaphore {
+ if maxPermits <= 0 {
+ log.Fatal("Max permits for semaphore needs to be > 0")
+ }
+
+ return &semaphore{
+ maxPermits: maxPermits,
+ permits: 0,
+ ch: make(chan bool),
+ }
+}
+
+func (s *semaphore) Acquire(ctx context.Context) bool {
+ permits := atomic.AddInt32(&s.permits, 1)
+ if permits <= s.maxPermits {
+ return true
+ }
+
+ // Block on the channel until a new permit is available
+ // or the context expires
+ select {
+ case <-s.ch:
+ return true
+ case <-ctx.Done():
+ atomic.AddInt32(&s.permits, -1)
+ return false
+ }
+}
+
+func (s *semaphore) TryAcquire() bool {
+ for {
+ currentPermits := atomic.LoadInt32(&s.permits)
+ if currentPermits >= s.maxPermits {
+ // All the permits are already exhausted
+ return false
+ }
+
+ if atomic.CompareAndSwapInt32(&s.permits, currentPermits, currentPermits+1) {
+ // Successfully incremented counter
+ return true
+ }
+ }
+}
+
+func (s *semaphore) Release() {
+ permits := atomic.AddInt32(&s.permits, -1)
+ if permits >= s.maxPermits {
+ // Unblock the next in line to acquire the semaphore
+ s.ch <- true
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/service_name_resolver.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/service_name_resolver.go
new file mode 100644
index 00000000..419f8be9
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/service_name_resolver.go
@@ -0,0 +1,128 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "errors"
+ "fmt"
+ "math/rand"
+ "net/url"
+ "sync"
+ "time"
+
+ log "github.com/sirupsen/logrus"
+)
+
+type ServiceNameResolver interface {
+ ResolveHost() (*url.URL, error)
+ ResolveHostURI() (*PulsarServiceURI, error)
+ UpdateServiceURL(url *url.URL) error
+ GetServiceURI() *PulsarServiceURI
+ GetServiceURL() *url.URL
+ GetAddressList() []*url.URL
+}
+
+type pulsarServiceNameResolver struct {
+ ServiceURI *PulsarServiceURI
+ ServiceURL *url.URL
+ CurrentIndex int32
+ AddressList []*url.URL
+
+ mutex sync.Mutex
+}
+
+func init() {
+ rand.Seed(time.Now().UnixNano())
+}
+
+func NewPulsarServiceNameResolver(url *url.URL) ServiceNameResolver {
+ r := &pulsarServiceNameResolver{}
+ err := r.UpdateServiceURL(url)
+ if err != nil {
+ log.Errorf("create pulsar service name resolver failed : %v", err)
+ }
+ return r
+}
+
+func (r *pulsarServiceNameResolver) ResolveHost() (*url.URL, error) {
+ r.mutex.Lock()
+ defer r.mutex.Unlock()
+
+ if r.AddressList == nil {
+ return nil, errors.New("no service url is provided yet")
+ }
+ if len(r.AddressList) == 0 {
+ return nil, fmt.Errorf("no hosts found for service url : %v", r.ServiceURL)
+ }
+ if len(r.AddressList) == 1 {
+ return r.AddressList[0], nil
+ }
+ idx := (r.CurrentIndex + 1) % int32(len(r.AddressList))
+ r.CurrentIndex = idx
+ return r.AddressList[idx], nil
+}
+
+func (r *pulsarServiceNameResolver) ResolveHostURI() (*PulsarServiceURI, error) {
+ host, err := r.ResolveHost()
+ if err != nil {
+ return nil, err
+ }
+ hostURL := host.Scheme + "://" + host.Hostname() + ":" + host.Port()
+ return NewPulsarServiceURIFromURIString(hostURL)
+}
+
+func (r *pulsarServiceNameResolver) UpdateServiceURL(u *url.URL) error {
+ uri, err := NewPulsarServiceURIFromURL(u)
+ if err != nil {
+ log.Errorf("invalid service-url instance %s provided %v", u, err)
+ return err
+ }
+
+ hosts := uri.ServiceHosts
+ addresses := []*url.URL{}
+ for _, host := range hosts {
+ hostURL := uri.URL.Scheme + "://" + host
+ u, err := url.Parse(hostURL)
+ if err != nil {
+ log.Errorf("invalid host-url %s provided %v", hostURL, err)
+ return err
+ }
+ addresses = append(addresses, u)
+ }
+
+ r.mutex.Lock()
+ defer r.mutex.Unlock()
+
+ r.AddressList = addresses
+ r.ServiceURL = u
+ r.ServiceURI = uri
+ r.CurrentIndex = int32(rand.Intn(len(addresses)))
+ return nil
+}
+
+func (r *pulsarServiceNameResolver) GetServiceURI() *PulsarServiceURI {
+ return r.ServiceURI
+}
+
+func (r *pulsarServiceNameResolver) GetServiceURL() *url.URL {
+ return r.ServiceURL
+}
+
+func (r *pulsarServiceNameResolver) GetAddressList() []*url.URL {
+ return r.AddressList
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/service_uri.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/service_uri.go
new file mode 100644
index 00000000..7b753398
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/service_uri.go
@@ -0,0 +1,211 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "strings"
+
+ log "github.com/sirupsen/logrus"
+)
+
+const (
+ BinaryService = "pulsar"
+ HTTPService = "http"
+ HTTPSService = "https"
+ SSLService = "ssl"
+ BinaryPort = 6650
+ BinaryTLSPort = 6651
+ HTTPPort = 80
+ HTTPSPort = 443
+)
+
+type PulsarServiceURI struct {
+ ServiceName string
+ ServiceInfos []string
+ ServiceHosts []string
+ servicePath string
+ URL *url.URL
+}
+
+func NewPulsarServiceURIFromURIString(uri string) (*PulsarServiceURI, error) {
+ u, err := fromString(uri)
+ if err != nil {
+ log.Error(err)
+ return nil, err
+ }
+ return u, nil
+}
+
+func NewPulsarServiceURIFromURL(url *url.URL) (*PulsarServiceURI, error) {
+ u, err := fromURL(url)
+ if err != nil {
+ log.Error(err)
+ return nil, err
+ }
+ return u, nil
+}
+
+func fromString(uriStr string) (*PulsarServiceURI, error) {
+ if uriStr == "" || len(uriStr) == 0 {
+ return nil, errors.New("service uriStr string is null")
+ }
+ if strings.Contains(uriStr, "[") && strings.Contains(uriStr, "]") {
+ // deal with ipv6 address
+ hosts := strings.FieldsFunc(uriStr, splitURI)
+ if len(hosts) > 1 {
+ // deal with ipv6 address
+ firstHost := hosts[0]
+ lastHost := hosts[len(hosts)-1]
+ hasPath := strings.Contains(lastHost, "/")
+ path := ""
+ if hasPath {
+ idx := strings.Index(lastHost, "/")
+ path = lastHost[idx:]
+ }
+ firstHost += path
+ url, err := url.Parse(firstHost)
+ if err != nil {
+ return nil, err
+ }
+ serviceURI, err := fromURL(url)
+ if err != nil {
+ return nil, err
+ }
+ var mHosts []string
+ var multiHosts []string
+ mHosts = append(mHosts, serviceURI.ServiceHosts[0])
+ mHosts = append(mHosts, hosts[1:]...)
+
+ for _, v := range mHosts {
+ h, err := validateHostName(serviceURI.ServiceName, serviceURI.ServiceInfos, v)
+ if err == nil {
+ multiHosts = append(multiHosts, h)
+ } else {
+ return nil, err
+ }
+ }
+
+ return &PulsarServiceURI{
+ serviceURI.ServiceName,
+ serviceURI.ServiceInfos,
+ multiHosts,
+ serviceURI.servicePath,
+ serviceURI.URL,
+ }, nil
+ }
+ }
+
+ url, err := url.Parse(uriStr)
+ if err != nil {
+ return nil, err
+ }
+
+ return fromURL(url)
+}
+
+func fromURL(url *url.URL) (*PulsarServiceURI, error) {
+ if url == nil {
+ return nil, errors.New("service url instance is null")
+ }
+
+ if url.Host == "" || len(url.Host) == 0 {
+ return nil, errors.New("service host is null")
+ }
+
+ var serviceName string
+ var serviceInfos []string
+ scheme := url.Scheme
+ if scheme != "" {
+ scheme = strings.ToLower(scheme)
+ schemeParts := strings.Split(scheme, "+")
+ serviceName = schemeParts[0]
+ serviceInfos = schemeParts[1:]
+ }
+
+ var serviceHosts []string
+ hosts := strings.FieldsFunc(url.Host, splitURI)
+ for _, v := range hosts {
+ h, err := validateHostName(serviceName, serviceInfos, v)
+ if err == nil {
+ serviceHosts = append(serviceHosts, h)
+ } else {
+ return nil, err
+ }
+ }
+
+ return &PulsarServiceURI{
+ serviceName,
+ serviceInfos,
+ serviceHosts,
+ url.Path,
+ url,
+ }, nil
+}
+
+func splitURI(r rune) bool {
+ return r == ',' || r == ';'
+}
+
+func validateHostName(serviceName string, serviceInfos []string, hostname string) (string, error) {
+ uri, err := url.Parse("dummyscheme://" + hostname)
+ if err != nil {
+ return "", err
+ }
+ host := uri.Hostname()
+ if strings.Contains(hostname, "[") && strings.Contains(hostname, "]") {
+ host = fmt.Sprintf("[%s]", host)
+ }
+ if host == "" || uri.Scheme == "" {
+ return "", errors.New("Invalid hostname : " + hostname)
+ }
+
+ port := uri.Port()
+ if uri.Port() == "" {
+ p := getServicePort(serviceName, serviceInfos)
+ if p == -1 {
+ return "", fmt.Errorf("invalid port : %d", p)
+ }
+ port = fmt.Sprint(p)
+ }
+ result := host + ":" + port
+ _, _, err = net.SplitHostPort(result)
+ if err != nil {
+ return "", err
+ }
+ return result, nil
+}
+
+func getServicePort(serviceName string, serviceInfos []string) int {
+ switch strings.ToLower(serviceName) {
+ case BinaryService:
+ if len(serviceInfos) == 0 {
+ return BinaryPort
+ } else if len(serviceInfos) == 1 && strings.ToLower(serviceInfos[0]) == SSLService {
+ return BinaryTLSPort
+ }
+ case HTTPService:
+ return HTTPPort
+ case HTTPSService:
+ return HTTPSPort
+ }
+ return -1
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/topic_name.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/topic_name.go
new file mode 100644
index 00000000..481e41f5
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/topic_name.go
@@ -0,0 +1,140 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "errors"
+ "fmt"
+ "net/url"
+ "strconv"
+ "strings"
+)
+
+// TopicName abstract a struct contained in a Topic
+type TopicName struct {
+ Domain string
+ Tenant string
+ Namespace string
+ Topic string
+ Name string
+ Partition int
+}
+
+const (
+ publicTenant = "public"
+ defaultNamespace = "default"
+ partitionedTopicSuffix = "-partition-"
+)
+
+// ParseTopicName parse the given topic name and return TopicName.
+func ParseTopicName(topic string) (*TopicName, error) {
+ // The topic name can be in two different forms, one is fully qualified topic name,
+ // the other one is short topic name
+ if !strings.Contains(topic, "://") {
+ // The short topic name can be:
+ // -
+ // - //
+ // - ///
+ parts := strings.Split(topic, "/")
+ if len(parts) == 3 || len(parts) == 4 {
+ topic = "persistent://" + topic
+ } else if len(parts) == 1 {
+ topic = "persistent://" + publicTenant + "/" + defaultNamespace + "/" + parts[0]
+ } else {
+ return nil, errors.New(
+ "Invalid short topic name '" + topic +
+ "', it should be in the format of // or ")
+ }
+ }
+
+ tn := &TopicName{}
+
+ // The fully qualified topic name can be in two different forms:
+ // new: persistent://tenant/namespace/topic
+ // legacy: persistent://tenant/cluster/namespace/topic
+ parts := strings.SplitN(topic, "://", 2)
+ domain := parts[0]
+ if domain != "persistent" && domain != "non-persistent" {
+ return nil, errors.New("Invalid topic domain: " + domain)
+ }
+ tn.Domain = domain
+
+ rest := parts[1]
+ var err error
+
+ // The rest of the name can be in different forms:
+ // new: tenant/namespace/
+ // legacy: tenant/cluster/namespace/
+ // Examples of localName:
+ // 1. some/name/xyz//
+ // 2. /xyz-123/feeder-2
+ parts = strings.SplitN(rest, "/", 4)
+ tn.Tenant = parts[0]
+ if len(parts) == 3 {
+ // New topic name without cluster name
+ tn.Namespace = parts[0] + "/" + parts[1]
+ tn.Topic = parts[2]
+ } else if len(parts) == 4 {
+ // Legacy topic name that includes cluster name
+ tn.Namespace = fmt.Sprintf("%s/%s/%s", parts[0], parts[1], parts[2])
+ tn.Topic = parts[3]
+ } else {
+ return nil, errors.New("Invalid topic name: " + topic)
+ }
+
+ tn.Name = topic
+ tn.Partition, err = getPartitionIndex(topic)
+ if err != nil {
+ return nil, err
+ }
+
+ return tn, nil
+}
+
+func TopicNameWithoutPartitionPart(tn *TopicName) string {
+ if tn == nil {
+ return ""
+ }
+ if tn.Partition < 0 {
+ return tn.Name
+ }
+ idx := strings.LastIndex(tn.Name, partitionedTopicSuffix)
+ if idx > 0 {
+ return tn.Name[:idx]
+ }
+ return tn.Name
+}
+
+func getPartitionIndex(topic string) (int, error) {
+ if strings.Contains(topic, partitionedTopicSuffix) {
+ idx := strings.LastIndex(topic, "-") + 1
+ return strconv.Atoi(topic[idx:])
+ }
+ return -1, nil
+}
+
+func IsV2TopicName(tn *TopicName) bool {
+ parts := strings.Split(tn.Namespace, "/")
+ // Legacy topic name that includes cluster name
+ // tn.Namespace = fmt.Sprintf("%s/%s/%s", parts[0], parts[1], parts[2])
+ return len(parts) != 3
+}
+
+func GetTopicRestPath(tn *TopicName) string {
+ return fmt.Sprintf("%s/%s/%s", tn.Domain, tn.Namespace, url.QueryEscape(tn.Topic))
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/utils.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/utils.go
new file mode 100644
index 00000000..9378d9dc
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/utils.go
@@ -0,0 +1,87 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "strconv"
+ "strings"
+ "sync/atomic"
+ "time"
+
+ "google.golang.org/protobuf/proto"
+
+ "github.com/pkg/errors"
+)
+
+// TimestampMillis return a time unix nano.
+func TimestampMillis(t time.Time) uint64 {
+ // calling UnixNano on the zero Time is undefined
+ if t.IsZero() {
+ return 0
+ }
+ return uint64(t.UnixNano()) / uint64(time.Millisecond)
+}
+
+// GetAndAdd perform atomic read and update
+func GetAndAdd(n *uint64, diff uint64) uint64 {
+ for {
+ v := *n
+ if atomic.CompareAndSwapUint64(n, v, v+diff) {
+ return v
+ }
+ }
+}
+
+func ParseRelativeTimeInSeconds(relativeTime string) (time.Duration, error) {
+ if relativeTime == "" {
+ return -1, errors.New("time can not be empty")
+ }
+
+ unitTime := relativeTime[len(relativeTime)-1:]
+ t := relativeTime[:len(relativeTime)-1]
+ timeValue, err := strconv.ParseInt(t, 10, 64)
+ if err != nil {
+ return -1, errors.Errorf("invalid time '%s'", t)
+ }
+
+ switch strings.ToLower(unitTime) {
+ case "s":
+ return time.Duration(timeValue) * time.Second, nil
+ case "m":
+ return time.Duration(timeValue) * time.Minute, nil
+ case "h":
+ return time.Duration(timeValue) * time.Hour, nil
+ case "d":
+ return time.Duration(timeValue) * time.Hour * 24, nil
+ case "w":
+ return time.Duration(timeValue) * time.Hour * 24 * 7, nil
+ case "y":
+ return time.Duration(timeValue) * time.Hour * 24 * 7 * 365, nil
+ default:
+ return -1, errors.Errorf("invalid time unit '%s'", unitTime)
+ }
+}
+
+func MarshalToSizedBuffer(m proto.Message, out []byte) error {
+ b, err := proto.Marshal(m)
+ if err != nil {
+ return err
+ }
+ copy(out, b[:len(out)])
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/internal/version.go b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/version.go
new file mode 100644
index 00000000..089f0dd1
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/internal/version.go
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+ "runtime/debug"
+
+ "golang.org/x/mod/semver"
+)
+
+const (
+ pulsarClientGoModulePath = "github.com/apache/pulsar-client-go"
+)
+
+var (
+ Version string
+ ClientVersionString string
+)
+
+// init Initializes the module version information by reading
+// the built in golang build info. If the application was not built
+// using go modules then the version string will not be available.
+func init() {
+ if buildInfo, ok := debug.ReadBuildInfo(); ok {
+ for _, dep := range buildInfo.Deps {
+ if dep.Path == pulsarClientGoModulePath {
+ Version = semver.Canonical(dep.Version)
+ ClientVersionString = "Pulsar Go " + Version
+ return
+ }
+ }
+ }
+ Version = "unknown"
+ ClientVersionString = "Pulsar Go version unknown"
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/key_shared_policy.go b/vendor/github.com/apache/pulsar-client-go/pulsar/key_shared_policy.go
new file mode 100644
index 00000000..30c6dc4d
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/key_shared_policy.go
@@ -0,0 +1,107 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "fmt"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+)
+
+type KeySharedPolicyMode int
+
+const (
+ // KeySharedPolicyModeAutoSplit Auto split hash range key shared policy.
+ KeySharedPolicyModeAutoSplit KeySharedPolicyMode = iota
+ // KeySharedPolicyModeSticky is Sticky attach topic with fixed hash range.
+ KeySharedPolicyModeSticky
+)
+
+// KeySharedPolicy for KeyShared subscription
+type KeySharedPolicy struct {
+ //KeySharedPolicyMode
+ Mode KeySharedPolicyMode
+ //HashRanges value pair list
+ HashRanges []int
+ // If enabled, it will relax the ordering requirement, allowing the broker to send out-of-order messages in case of
+ // failures. This will make it faster for new consumers to join without being stalled by an existing slow consumer.
+ AllowOutOfOrderDelivery bool
+}
+
+// NewKeySharedPolicySticky construct KeySharedPolicy in Sticky mode with
+// hashRanges formed in value pair list: [x1, x2, y1, y2, z1, z2], and must not overlap with each others
+func NewKeySharedPolicySticky(hashRanges []int) (*KeySharedPolicy, error) {
+ err := validateHashRanges(hashRanges)
+ if err != nil {
+ return nil, err
+ }
+ return &KeySharedPolicy{
+ Mode: KeySharedPolicyModeSticky,
+ HashRanges: hashRanges,
+ }, nil
+}
+
+func toProtoKeySharedMeta(ksp *KeySharedPolicy) *pb.KeySharedMeta {
+ if ksp == nil {
+ return nil
+ }
+
+ mode := pb.KeySharedMode(ksp.Mode)
+ meta := &pb.KeySharedMeta{
+ KeySharedMode: &mode,
+ AllowOutOfOrderDelivery: &ksp.AllowOutOfOrderDelivery,
+ }
+
+ if ksp.Mode == KeySharedPolicyModeSticky {
+ for i := 0; i < len(ksp.HashRanges); i += 2 {
+ start, end := int32(ksp.HashRanges[i]), int32(ksp.HashRanges[i+1])
+ meta.HashRanges = append(meta.HashRanges, &pb.IntRange{Start: &start, End: &end})
+ }
+ }
+
+ return meta
+}
+
+func validateHashRanges(hashRanges []int) error {
+ sz := len(hashRanges)
+ if sz == 0 || sz%2 != 0 {
+ return fmt.Errorf("ranges must not be empty or not in value pairs")
+ }
+ var x1, x2, y1, y2 int
+ //check that the ranges are well-formed
+ for i := 0; i < sz; i += 2 {
+ x1, x2 = hashRanges[i], hashRanges[i+1]
+ if x1 >= x2 || x1 < 0 || x2 > 65535 {
+ return fmt.Errorf("ranges must be in [0, 65535], but provided range is, %d - %d", x1, x2)
+ }
+ }
+ //loop again for checking range overlap
+ for i := 0; i < sz; i += 2 {
+ x1, x2 = hashRanges[i], hashRanges[i+1]
+ for j := 0; j < sz; j += 2 {
+ if j == i {
+ continue
+ }
+ y1, y2 = hashRanges[j], hashRanges[j+1]
+ if x1 <= y2 && y1 <= x2 {
+ return fmt.Errorf("ranges with overlap between, %d - %d, and %d - %d", x1, x2, y1, y2)
+ }
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/log/log.go b/vendor/github.com/apache/pulsar-client-go/pulsar/log/log.go
new file mode 100644
index 00000000..7ed52317
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/log/log.go
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package log
+
+// DefaultNopLogger returns a nop logger.
+func DefaultNopLogger() Logger {
+ return nopLogger{}
+}
+
+type nopLogger struct{}
+
+func (l nopLogger) SubLogger(fields Fields) Logger { return l }
+func (l nopLogger) WithFields(fields Fields) Entry { return nopEntry{} }
+func (l nopLogger) WithField(name string, value interface{}) Entry { return nopEntry{} }
+func (l nopLogger) WithError(err error) Entry { return nopEntry{} }
+func (l nopLogger) Debug(args ...interface{}) {}
+func (l nopLogger) Info(args ...interface{}) {}
+func (l nopLogger) Warn(args ...interface{}) {}
+func (l nopLogger) Error(args ...interface{}) {}
+func (l nopLogger) Debugf(format string, args ...interface{}) {}
+func (l nopLogger) Infof(format string, args ...interface{}) {}
+func (l nopLogger) Warnf(format string, args ...interface{}) {}
+func (l nopLogger) Errorf(format string, args ...interface{}) {}
+
+type nopEntry struct{}
+
+func (e nopEntry) WithFields(fields Fields) Entry { return nopEntry{} }
+func (e nopEntry) WithField(name string, value interface{}) Entry { return nopEntry{} }
+
+func (e nopEntry) Debug(args ...interface{}) {}
+func (e nopEntry) Info(args ...interface{}) {}
+func (e nopEntry) Warn(args ...interface{}) {}
+func (e nopEntry) Error(args ...interface{}) {}
+func (e nopEntry) Debugf(format string, args ...interface{}) {}
+func (e nopEntry) Infof(format string, args ...interface{}) {}
+func (e nopEntry) Warnf(format string, args ...interface{}) {}
+func (e nopEntry) Errorf(format string, args ...interface{}) {}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/log/logger.go b/vendor/github.com/apache/pulsar-client-go/pulsar/log/logger.go
new file mode 100644
index 00000000..693416c6
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/log/logger.go
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Package log defines the logger interfaces used by pulsar client.
+// Users can leverage these interfaces to provide a customized logger
+// implementation.
+//
+// The Logger and Entry interfaces defined here are inspired
+// by sirupsen/logrus, both logrus and zap logging libraries
+// are good resources to learn how to implement a effective
+// logging library.
+//
+// Besides the interfaces, this log library also provides an
+// implementation based on logrus, and a No-op one as well.
+package log
+
+// Fields type, used to pass to `WithFields`.
+type Fields map[string]interface{}
+
+// Logger describes the interface that must be implemeted by all loggers.
+type Logger interface {
+ SubLogger(fields Fields) Logger
+
+ WithFields(fields Fields) Entry
+ WithField(name string, value interface{}) Entry
+ WithError(err error) Entry
+
+ Debug(args ...interface{})
+ Info(args ...interface{})
+ Warn(args ...interface{})
+ Error(args ...interface{})
+
+ Debugf(format string, args ...interface{})
+ Infof(format string, args ...interface{})
+ Warnf(format string, args ...interface{})
+ Errorf(format string, args ...interface{})
+}
+
+// Entry describes the interface for the logger entry.
+type Entry interface {
+ WithFields(fields Fields) Entry
+ WithField(name string, value interface{}) Entry
+
+ Debug(args ...interface{})
+ Info(args ...interface{})
+ Warn(args ...interface{})
+ Error(args ...interface{})
+
+ Debugf(format string, args ...interface{})
+ Infof(format string, args ...interface{})
+ Warnf(format string, args ...interface{})
+ Errorf(format string, args ...interface{})
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/log/wrapper_logrus.go b/vendor/github.com/apache/pulsar-client-go/pulsar/log/wrapper_logrus.go
new file mode 100644
index 00000000..b8f94d0d
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/log/wrapper_logrus.go
@@ -0,0 +1,140 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package log
+
+import (
+ "github.com/sirupsen/logrus"
+)
+
+// logrusWrapper implements Logger interface
+// based on underlying logrus.FieldLogger
+type logrusWrapper struct {
+ l logrus.FieldLogger
+}
+
+// NewLoggerWithLogrus creates a new logger which wraps
+// the given logrus.Logger
+func NewLoggerWithLogrus(logger *logrus.Logger) Logger {
+ return &logrusWrapper{
+ l: logger,
+ }
+}
+
+func (l *logrusWrapper) SubLogger(fs Fields) Logger {
+ return &logrusWrapper{
+ l: l.l.WithFields(logrus.Fields(fs)),
+ }
+}
+
+func (l *logrusWrapper) WithFields(fs Fields) Entry {
+ return logrusEntry{
+ e: l.l.WithFields(logrus.Fields(fs)),
+ }
+}
+
+func (l *logrusWrapper) WithField(name string, value interface{}) Entry {
+ return logrusEntry{
+ e: l.l.WithField(name, value),
+ }
+}
+
+func (l *logrusWrapper) WithError(err error) Entry {
+ return logrusEntry{
+ e: l.l.WithError(err),
+ }
+}
+
+func (l *logrusWrapper) Debug(args ...interface{}) {
+ l.l.Debug(args...)
+}
+
+func (l *logrusWrapper) Info(args ...interface{}) {
+ l.l.Info(args...)
+}
+
+func (l *logrusWrapper) Warn(args ...interface{}) {
+ l.l.Warn(args...)
+}
+
+func (l *logrusWrapper) Error(args ...interface{}) {
+ l.l.Error(args...)
+}
+
+func (l *logrusWrapper) Debugf(format string, args ...interface{}) {
+ l.l.Debugf(format, args...)
+}
+
+func (l *logrusWrapper) Infof(format string, args ...interface{}) {
+ l.l.Infof(format, args...)
+}
+
+func (l *logrusWrapper) Warnf(format string, args ...interface{}) {
+ l.l.Warnf(format, args...)
+}
+
+func (l *logrusWrapper) Errorf(format string, args ...interface{}) {
+ l.l.Errorf(format, args...)
+}
+
+type logrusEntry struct {
+ e logrus.FieldLogger
+}
+
+func (l logrusEntry) WithFields(fs Fields) Entry {
+ return logrusEntry{
+ e: l.e.WithFields(logrus.Fields(fs)),
+ }
+}
+
+func (l logrusEntry) WithField(name string, value interface{}) Entry {
+ return logrusEntry{
+ e: l.e.WithField(name, value),
+ }
+}
+
+func (l logrusEntry) Debug(args ...interface{}) {
+ l.e.Debug(args...)
+}
+
+func (l logrusEntry) Info(args ...interface{}) {
+ l.e.Info(args...)
+}
+
+func (l logrusEntry) Warn(args ...interface{}) {
+ l.e.Warn(args...)
+}
+
+func (l logrusEntry) Error(args ...interface{}) {
+ l.e.Error(args...)
+}
+
+func (l logrusEntry) Debugf(format string, args ...interface{}) {
+ l.e.Debugf(format, args...)
+}
+
+func (l logrusEntry) Infof(format string, args ...interface{}) {
+ l.e.Infof(format, args...)
+}
+
+func (l logrusEntry) Warnf(format string, args ...interface{}) {
+ l.e.Warnf(format, args...)
+}
+
+func (l logrusEntry) Errorf(format string, args ...interface{}) {
+ l.e.Errorf(format, args...)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/message.go b/vendor/github.com/apache/pulsar-client-go/pulsar/message.go
new file mode 100644
index 00000000..98190e91
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/message.go
@@ -0,0 +1,214 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "time"
+)
+
+// ProducerMessage abstraction used in Pulsar producer
+type ProducerMessage struct {
+ // Payload for the message
+ Payload []byte
+
+ // Value and payload is mutually exclusive, `Value interface{}` for schema message.
+ Value interface{}
+
+ // Key sets the key of the message for routing policy
+ Key string
+
+ // OrderingKey sets the ordering key of the message
+ OrderingKey string
+
+ // Properties attach application defined properties on the message
+ Properties map[string]string
+
+ // EventTime set the event time for a given message
+ // By default, messages don't have an event time associated, while the publish
+ // time will be be always present.
+ // Set the event time to a non-zero timestamp to explicitly declare the time
+ // that the event "happened", as opposed to when the message is being published.
+ EventTime time.Time
+
+ // ReplicationClusters override the replication clusters for this message.
+ ReplicationClusters []string
+
+ // DisableReplication disables the replication for this message
+ DisableReplication bool
+
+ // SequenceID sets the sequence id to assign to the current message
+ SequenceID *int64
+
+ // DeliverAfter requests to deliver the message only after the specified relative delay.
+ // Note: messages are only delivered with delay when a consumer is consuming
+ // through a `SubscriptionType=Shared` subscription. With other subscription
+ // types, the messages will still be delivered immediately.
+ DeliverAfter time.Duration
+
+ // DeliverAt delivers the message only at or after the specified absolute timestamp.
+ // Note: messages are only delivered with delay when a consumer is consuming
+ // through a `SubscriptionType=Shared` subscription. With other subscription
+ // types, the messages will still be delivered immediately.
+ DeliverAt time.Time
+
+ //Schema assign to the current message
+ //Note: messages may have a different schema from producer schema, use it instead of producer schema when assigned
+ Schema Schema
+}
+
+// Message abstraction used in Pulsar
+type Message interface {
+ // Topic returns the topic from which this message originated from.
+ Topic() string
+
+ // ProducerName returns the name of the producer that has published the message.
+ ProducerName() string
+
+ // Properties are application defined key/value pairs that will be attached to the message.
+ // Returns the properties attached to the message.
+ Properties() map[string]string
+
+ // Payload returns the payload of the message
+ Payload() []byte
+
+ // ID returns the unique message ID associated with this message.
+ // The message id can be used to univocally refer to a message without having the keep the entire payload in memory.
+ ID() MessageID
+
+ // PublishTime returns the publish time of this message. The publish time is the timestamp that a client
+ // publish the message.
+ PublishTime() time.Time
+
+ // EventTime returns the event time associated with this message. It is typically set by the applications via
+ // `ProducerMessage.EventTime`.
+ // If EventTime is 0, it means there isn't any event time associated with this message.
+ EventTime() time.Time
+
+ // Key returns the key of the message, if any
+ Key() string
+
+ // OrderingKey returns the ordering key of the message, if any
+ OrderingKey() string
+
+ // RedeliveryCount returns message redelivery count, redelivery count maintain in pulsar broker.
+ // When client nack acknowledge messages,
+ // broker will dispatch message again with message redelivery count in CommandMessage defined.
+ //
+ // Message redelivery increases monotonically in a broker, when topic switch ownership to a another broker
+ // redelivery count will be recalculated.
+ RedeliveryCount() uint32
+
+ // IsReplicated determines whether the message is replicated from another cluster.
+ IsReplicated() bool
+
+ // GetReplicatedFrom returns the name of the cluster, from which the message is replicated.
+ GetReplicatedFrom() string
+
+ // GetSchemaValue returns the de-serialized value of the message, according to the configuration.
+ GetSchemaValue(v interface{}) error
+
+ //SchemaVersion get the schema version of the message, if any
+ SchemaVersion() []byte
+
+ // GetEncryptionContext returns the ecryption context of the message.
+ // It will be used by the application to parse the undecrypted message.
+ GetEncryptionContext() *EncryptionContext
+
+ // Index returns index from broker entry metadata,
+ // or empty if the feature is not enabled in the broker.
+ Index() *uint64
+
+ // BrokerPublishTime returns broker publish time from broker entry metadata,
+ // or empty if the feature is not enabled in the broker.
+ BrokerPublishTime() *time.Time
+}
+
+// MessageID identifier for a particular message
+type MessageID interface {
+ // Serialize the message id into a sequence of bytes that can be stored somewhere else
+ Serialize() []byte
+
+ // LedgerID returns the message ledgerID
+ LedgerID() int64
+
+ // EntryID returns the message entryID
+ EntryID() int64
+
+ // BatchIdx returns the message batchIdx
+ BatchIdx() int32
+
+ // PartitionIdx returns the message partitionIdx
+ PartitionIdx() int32
+
+ // BatchSize returns 0 or the batch size, which must be greater than BatchIdx()
+ BatchSize() int32
+
+ // String returns message id in string format
+ String() string
+}
+
+// DeserializeMessageID reconstruct a MessageID object from its serialized representation
+func DeserializeMessageID(data []byte) (MessageID, error) {
+ return deserializeMessageID(data)
+}
+
+// NewMessageID Custom Create MessageID
+func NewMessageID(ledgerID int64, entryID int64, batchIdx int32, partitionIdx int32) MessageID {
+ return newMessageID(ledgerID, entryID, batchIdx, partitionIdx, 0)
+}
+
+// EarliestMessageID returns a messageID that points to the earliest message available in a topic
+func EarliestMessageID() MessageID {
+ return earliestMessageID
+}
+
+// LatestMessageID returns a messageID that points to the latest message
+func LatestMessageID() MessageID {
+ return latestMessageID
+}
+
+func messageIDCompare(lhs MessageID, rhs MessageID) int {
+ if lhs.LedgerID() < rhs.LedgerID() {
+ return -1
+ } else if lhs.LedgerID() > rhs.LedgerID() {
+ return 1
+ }
+ if lhs.EntryID() < rhs.EntryID() {
+ return -1
+ } else if lhs.EntryID() > rhs.EntryID() {
+ return 1
+ }
+ // When performing batch index ACK on a batched message whose batch size is N,
+ // the ACK order should be:
+ // (ledger, entry, 0) -> (ledger, entry, 1) -> ... -> (ledger, entry, N-1) -> (ledger, entry)
+ // So we have to treat any MessageID with the batch index precedes the MessageID without the batch index
+ // if they are in the same entry.
+ if lhs.BatchIdx() < 0 && rhs.BatchIdx() < 0 {
+ return 0
+ } else if lhs.BatchIdx() >= 0 && rhs.BatchIdx() < 0 {
+ return -1
+ } else if lhs.BatchIdx() < 0 && rhs.BatchIdx() >= 0 {
+ return 1
+ }
+ if lhs.BatchIdx() < rhs.BatchIdx() {
+ return -1
+ } else if lhs.BatchIdx() > rhs.BatchIdx() {
+ return 1
+ }
+ return 0
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/negative_acks_tracker.go b/vendor/github.com/apache/pulsar-client-go/pulsar/negative_acks_tracker.go
new file mode 100644
index 00000000..58f56767
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/negative_acks_tracker.go
@@ -0,0 +1,155 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "sync"
+ "time"
+
+ log "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+type redeliveryConsumer interface {
+ Redeliver(msgIds []messageID)
+}
+
+type negativeAcksTracker struct {
+ sync.Mutex
+
+ doneCh chan interface{}
+ doneOnce sync.Once
+ negativeAcks map[messageID]time.Time
+ rc redeliveryConsumer
+ nackBackoff NackBackoffPolicy
+ tick *time.Ticker
+ delay time.Duration
+ log log.Logger
+}
+
+func newNegativeAcksTracker(rc redeliveryConsumer, delay time.Duration,
+ nackBackoffPolicy NackBackoffPolicy, logger log.Logger) *negativeAcksTracker {
+
+ t := &negativeAcksTracker{
+ doneCh: make(chan interface{}),
+ negativeAcks: make(map[messageID]time.Time),
+ rc: rc,
+ nackBackoff: nackBackoffPolicy,
+ log: logger,
+ }
+
+ if nackBackoffPolicy != nil {
+ firstDelayForNackBackoff := nackBackoffPolicy.Next(1)
+ t.delay = firstDelayForNackBackoff
+ } else {
+ t.delay = delay
+ }
+
+ t.tick = time.NewTicker(t.delay / 3)
+
+ go t.track()
+ return t
+}
+
+func (t *negativeAcksTracker) Add(msgID *messageID) {
+ // Always clear up the batch index since we want to track the nack
+ // for the entire batch
+ batchMsgID := messageID{
+ ledgerID: msgID.ledgerID,
+ entryID: msgID.entryID,
+ batchIdx: 0,
+ }
+
+ t.Lock()
+ defer t.Unlock()
+
+ _, present := t.negativeAcks[batchMsgID]
+ if present {
+ // The batch is already being tracked
+ return
+ }
+
+ targetTime := time.Now().Add(t.delay)
+ t.negativeAcks[batchMsgID] = targetTime
+}
+
+func (t *negativeAcksTracker) AddMessage(msg Message) {
+ nackBackoffDelay := t.nackBackoff.Next(msg.RedeliveryCount())
+
+ msgID := msg.ID()
+
+ // Always clear up the batch index since we want to track the nack
+ // for the entire batch
+ batchMsgID := messageID{
+ ledgerID: msgID.LedgerID(),
+ entryID: msgID.EntryID(),
+ batchIdx: 0,
+ }
+
+ t.Lock()
+ defer t.Unlock()
+
+ _, present := t.negativeAcks[batchMsgID]
+ if present {
+ // The batch is already being tracked
+ return
+ }
+
+ targetTime := time.Now().Add(nackBackoffDelay)
+ t.negativeAcks[batchMsgID] = targetTime
+}
+
+func (t *negativeAcksTracker) track() {
+ for {
+ select {
+ case <-t.doneCh:
+ t.log.Debug("Closing nack tracker")
+ return
+
+ case <-t.tick.C:
+ {
+ now := time.Now()
+ msgIds := make([]messageID, 0)
+
+ t.Lock()
+
+ for msgID, targetTime := range t.negativeAcks {
+ t.log.Debugf("MsgId: %v -- targetTime: %v -- now: %v", msgID, targetTime, now)
+ if targetTime.Before(now) {
+ t.log.Debugf("Adding MsgId: %v", msgID)
+ msgIds = append(msgIds, msgID)
+ delete(t.negativeAcks, msgID)
+ }
+ }
+
+ t.Unlock()
+
+ if len(msgIds) > 0 {
+ t.rc.Redeliver(msgIds)
+ }
+ }
+ }
+ }
+}
+
+func (t *negativeAcksTracker) Close() {
+ // allow Close() to be invoked multiple times by consumer_partition to avoid panic
+ t.doneOnce.Do(func() {
+ t.tick.Stop()
+ t.doneCh <- nil
+ })
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/negative_backoff_policy.go b/vendor/github.com/apache/pulsar-client-go/pulsar/negative_backoff_policy.go
new file mode 100644
index 00000000..5cd35bcf
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/negative_backoff_policy.go
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "math"
+ "time"
+)
+
+// NackBackoffPolicy is a interface for custom message negativeAcked policy, users can specify a NackBackoffPolicy
+// for a consumer.
+//
+// > Notice: the consumer crashes will trigger the redelivery of the unacked message, this case will not respect the
+// > NackBackoffPolicy, which means the message might get redelivered earlier than the delay time
+// > from the backoff.
+type NackBackoffPolicy interface {
+ // Next param redeliveryCount indicates the number of times the message was redelivered.
+ // We can get the redeliveryCount from the CommandMessage.
+ Next(redeliveryCount uint32) time.Duration
+}
+
+// defaultNackBackoffPolicy is default impl for NackBackoffPolicy.
+type defaultNackBackoffPolicy struct{}
+
+func (nbp *defaultNackBackoffPolicy) Next(redeliveryCount uint32) time.Duration {
+ minNackTime := 1 * time.Second // 1sec
+ maxNackTime := 10 * time.Minute // 10min
+
+ if redeliveryCount < 0 {
+ return minNackTime
+ }
+
+ return time.Duration(math.Min(math.Abs(float64(minNackTime<https://en.wikipedia.org/wiki/MurmurHash
+ //
+ // Default is `JavaStringHash`.
+ HashingScheme
+
+ // CompressionType specifies the compression type for the producer.
+ // By default, message payloads are not compressed. Supported compression types are:
+ // - LZ4
+ // - ZLIB
+ // - ZSTD
+ //
+ // Note: ZSTD is supported since Pulsar 2.3. Consumers will need to be at least at that
+ // release in order to be able to receive messages compressed with ZSTD.
+ CompressionType
+
+ // CompressionLevel defines the desired compression level. Options:
+ // - Default
+ // - Faster
+ // - Better
+ CompressionLevel
+
+ // MessageRouter represents a custom message routing policy by passing an implementation of MessageRouter
+ // The router is a function that given a particular message and the topic metadata, returns the
+ // partition index where the message should be routed to
+ MessageRouter func(*ProducerMessage, TopicMetadata) int
+
+ // DisableBatching controls whether automatic batching of messages is enabled for the producer. By default batching
+ // is enabled.
+ // When batching is enabled, multiple calls to Producer.sendAsync can result in a single batch to be sent to the
+ // broker, leading to better throughput, especially when publishing small messages. If compression is enabled,
+ // messages will be compressed at the batch level, leading to a much better compression ratio for similar headers or
+ // contents.
+ // When enabled default batch delay is set to 1 ms and default batch size is 1000 messages
+ // Setting `DisableBatching: true` will make the producer to send messages individually
+ DisableBatching bool
+
+ // BatchingMaxPublishDelay specifies the time period within which the messages sent will be batched (default: 10ms)
+ // if batch messages are enabled. If set to a non zero value, messages will be queued until this time
+ // interval or until
+ BatchingMaxPublishDelay time.Duration
+
+ // BatchingMaxMessages specifies the maximum number of messages permitted in a batch. (default: 1000)
+ // If set to a value greater than 1, messages will be queued until this threshold is reached or
+ // BatchingMaxSize (see below) has been reached or the batch interval has elapsed.
+ BatchingMaxMessages uint
+
+ // BatchingMaxSize specifies the maximum number of bytes permitted in a batch. (default 128 KB)
+ // If set to a value greater than 1, messages will be queued until this threshold is reached or
+ // BatchingMaxMessages (see above) has been reached or the batch interval has elapsed.
+ BatchingMaxSize uint
+
+ // Interceptors is a chain of interceptors, These interceptors will be called at some points defined
+ // in ProducerInterceptor interface
+ Interceptors ProducerInterceptors
+
+ // Schema represents the schema implementation.
+ Schema Schema
+
+ // MaxReconnectToBroker specifies the maximum retry number of reconnectToBroker. (default: ultimate)
+ MaxReconnectToBroker *uint
+
+ // BackoffPolicy parameterize the following options in the reconnection logic to
+ // allow users to customize the reconnection logic (minBackoff, maxBackoff and jitterPercentage)
+ BackoffPolicy internal.BackoffPolicy
+
+ // BatcherBuilderType sets the batch builder type (default DefaultBatchBuilder)
+ // This will be used to create batch container when batching is enabled.
+ // Options:
+ // - DefaultBatchBuilder
+ // - KeyBasedBatchBuilder
+ BatcherBuilderType
+
+ // PartitionsAutoDiscoveryInterval is the time interval for the background process to discover new partitions
+ // Default is 1 minute
+ PartitionsAutoDiscoveryInterval time.Duration
+
+ // Disable multiple Schame Version
+ // Default false
+ DisableMultiSchema bool
+
+ // Encryption specifies the fields required to encrypt a message
+ Encryption *ProducerEncryptionInfo
+
+ // EnableChunking controls whether automatic chunking of messages is enabled for the producer. By default, chunking
+ // is disabled.
+ // Chunking can not be enabled when batching is enabled.
+ EnableChunking bool
+
+ // ChunkMaxMessageSize is the max size of single chunk payload.
+ // It will actually only take effect if it is smaller than the maxMessageSize from the broker.
+ ChunkMaxMessageSize uint
+
+ // The type of access to the topic that the producer requires. (default ProducerAccessModeShared)
+ // Options:
+ // - ProducerAccessModeShared
+ // - ProducerAccessModeExclusive
+ ProducerAccessMode
+}
+
+// Producer is used to publish messages on a topic
+type Producer interface {
+ // Topic return the topic to which producer is publishing to
+ Topic() string
+
+ // Name return the producer name which could have been assigned by the system or specified by the client
+ Name() string
+
+ // Send a message
+ // This call will be blocking until is successfully acknowledged by the Pulsar broker.
+ // Example:
+ // producer.Send(ctx, pulsar.ProducerMessage{ Payload: myPayload })
+ Send(context.Context, *ProducerMessage) (MessageID, error)
+
+ // SendAsync a message in asynchronous mode
+ // This call is blocked when the `event channel` becomes full (default: 10) or the
+ // `maxPendingMessages` becomes full (default: 1000)
+ // The callback will report back the message being published and
+ // the eventual error in publishing
+ SendAsync(context.Context, *ProducerMessage, func(MessageID, *ProducerMessage, error))
+
+ // LastSequenceID get the last sequence id that was published by this producer.
+ // This represent either the automatically assigned or custom sequence id (set on the ProducerMessage) that
+ // was published and acknowledged by the broker.
+ // After recreating a producer with the same producer name, this will return the last message that was
+ // published in the previous producer session, or -1 if there no message was ever published.
+ // return the last sequence id published by this producer.
+ LastSequenceID() int64
+
+ // Flush all the messages buffered in the client and wait until all messages have been successfully
+ // persisted.
+ Flush() error
+
+ // Close the producer and releases resources allocated
+ // No more writes will be accepted from this producer. Waits until all pending write request are persisted. In case
+ // of errors, pending writes will not be retried.
+ Close()
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/producer_impl.go b/vendor/github.com/apache/pulsar-client-go/pulsar/producer_impl.go
new file mode 100644
index 00000000..3c45b597
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/producer_impl.go
@@ -0,0 +1,363 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "fmt"
+ "sync"
+ "sync/atomic"
+ "time"
+ "unsafe"
+
+ "github.com/apache/pulsar-client-go/pulsar/crypto"
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+const (
+ // defaultSendTimeout init default timeout for ack since sent.
+ defaultSendTimeout = 30 * time.Second
+
+ // defaultBatchingMaxPublishDelay init default for maximum delay to batch messages
+ defaultBatchingMaxPublishDelay = 10 * time.Millisecond
+
+ // defaultMaxBatchSize init default for maximum number of bytes per batch
+ defaultMaxBatchSize = 128 * 1024
+
+ // defaultMaxMessagesPerBatch init default num of entries in per batch.
+ defaultMaxMessagesPerBatch = 1000
+
+ // defaultPartitionsAutoDiscoveryInterval init default time interval for partitions auto discovery
+ defaultPartitionsAutoDiscoveryInterval = 1 * time.Minute
+)
+
+type producer struct {
+ sync.RWMutex
+ client *client
+ options *ProducerOptions
+ topic string
+ producers []Producer
+ producersPtr unsafe.Pointer
+ numPartitions uint32
+ messageRouter func(*ProducerMessage, TopicMetadata) int
+ closeOnce sync.Once
+ stopDiscovery func()
+ log log.Logger
+ metrics *internal.LeveledMetrics
+}
+
+func getHashingFunction(s HashingScheme) func(string) uint32 {
+ switch s {
+ case JavaStringHash:
+ return internal.JavaStringHash
+ case Murmur3_32Hash:
+ return internal.Murmur3_32Hash
+ default:
+ return internal.JavaStringHash
+ }
+}
+
+func newProducer(client *client, options *ProducerOptions) (*producer, error) {
+ if options.Topic == "" {
+ return nil, newError(InvalidTopicName, "Topic name is required for producer")
+ }
+
+ if options.SendTimeout == 0 {
+ options.SendTimeout = defaultSendTimeout
+ }
+ if options.BatchingMaxMessages == 0 {
+ options.BatchingMaxMessages = defaultMaxMessagesPerBatch
+ }
+ if options.BatchingMaxSize == 0 {
+ options.BatchingMaxSize = defaultMaxBatchSize
+ }
+ if options.BatchingMaxPublishDelay <= 0 {
+ options.BatchingMaxPublishDelay = defaultBatchingMaxPublishDelay
+ }
+ if options.PartitionsAutoDiscoveryInterval <= 0 {
+ options.PartitionsAutoDiscoveryInterval = defaultPartitionsAutoDiscoveryInterval
+ }
+
+ if !options.DisableBatching && options.EnableChunking {
+ return nil, fmt.Errorf("batching and chunking can not be enabled together")
+ }
+
+ p := &producer{
+ options: options,
+ topic: options.Topic,
+ client: client,
+ log: client.log.SubLogger(log.Fields{"topic": options.Topic}),
+ metrics: client.metrics.GetLeveledMetrics(options.Topic),
+ }
+
+ if options.Interceptors == nil {
+ options.Interceptors = defaultProducerInterceptors
+ }
+
+ if options.MessageRouter == nil {
+ internalRouter := NewDefaultRouter(
+ getHashingFunction(options.HashingScheme),
+ options.BatchingMaxMessages,
+ options.BatchingMaxSize,
+ options.BatchingMaxPublishDelay,
+ options.DisableBatching)
+ p.messageRouter = func(message *ProducerMessage, metadata TopicMetadata) int {
+ return internalRouter(message, metadata.NumPartitions())
+ }
+ } else {
+ p.messageRouter = options.MessageRouter
+ }
+
+ if options.Schema != nil && options.Schema.GetSchemaInfo() != nil {
+ if options.Schema.GetSchemaInfo().Type == NONE {
+ options.Schema = NewBytesSchema(nil)
+ }
+ }
+
+ encryption := options.Encryption
+ // add default message crypto if not provided
+ if encryption != nil && len(encryption.Keys) > 0 {
+ if encryption.KeyReader == nil {
+ return nil, fmt.Errorf("encryption is enabled, KeyReader can not be nil")
+ }
+
+ if encryption.MessageCrypto == nil {
+ logCtx := fmt.Sprintf("[%v] [%v]", p.topic, p.options.Name)
+ messageCrypto, err := crypto.NewDefaultMessageCrypto(logCtx,
+ true,
+ client.log.SubLogger(log.Fields{"topic": p.topic}))
+ if err != nil {
+ return nil, fmt.Errorf("unable to get MessageCrypto instance. Producer creation is abandoned. %v", err)
+ }
+ p.options.Encryption.MessageCrypto = messageCrypto
+ }
+ }
+
+ err := p.internalCreatePartitionsProducers()
+ if err != nil {
+ return nil, err
+ }
+
+ p.stopDiscovery = p.runBackgroundPartitionDiscovery(options.PartitionsAutoDiscoveryInterval)
+
+ p.metrics.ProducersOpened.Inc()
+ return p, nil
+}
+
+func (p *producer) runBackgroundPartitionDiscovery(period time.Duration) (cancel func()) {
+ var wg sync.WaitGroup
+ stopDiscoveryCh := make(chan struct{})
+ ticker := time.NewTicker(period)
+
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for {
+ select {
+ case <-stopDiscoveryCh:
+ return
+ case <-ticker.C:
+ p.log.Debug("Auto discovering new partitions")
+ p.internalCreatePartitionsProducers()
+ }
+ }
+ }()
+
+ return func() {
+ ticker.Stop()
+ close(stopDiscoveryCh)
+ wg.Wait()
+ }
+}
+
+func (p *producer) internalCreatePartitionsProducers() error {
+ partitions, err := p.client.TopicPartitions(p.topic)
+ if err != nil {
+ return err
+ }
+
+ oldNumPartitions := 0
+ newNumPartitions := len(partitions)
+
+ p.Lock()
+ defer p.Unlock()
+
+ oldProducers := p.producers
+ oldNumPartitions = len(oldProducers)
+
+ if oldProducers != nil {
+ if oldNumPartitions == newNumPartitions {
+ p.log.Debug("Number of partitions in topic has not changed")
+ return nil
+ }
+
+ p.log.WithField("old_partitions", oldNumPartitions).
+ WithField("new_partitions", newNumPartitions).
+ Info("Changed number of partitions in topic")
+
+ }
+
+ p.producers = make([]Producer, newNumPartitions)
+
+ // When for some reason (eg: forced deletion of sub partition) causes oldNumPartitions> newNumPartitions,
+ // we need to rebuild the cache of new producers, otherwise the array will be out of bounds.
+ if oldProducers != nil && oldNumPartitions < newNumPartitions {
+ // Copy over the existing consumer instances
+ for i := 0; i < oldNumPartitions; i++ {
+ p.producers[i] = oldProducers[i]
+ }
+ }
+
+ type ProducerError struct {
+ partition int
+ prod Producer
+ err error
+ }
+
+ startPartition := oldNumPartitions
+ partitionsToAdd := newNumPartitions - oldNumPartitions
+ if partitionsToAdd < 0 {
+ partitionsToAdd = newNumPartitions
+ startPartition = 0
+ }
+ c := make(chan ProducerError, partitionsToAdd)
+
+ for partitionIdx := startPartition; partitionIdx < newNumPartitions; partitionIdx++ {
+ partition := partitions[partitionIdx]
+
+ go func(partitionIdx int, partition string) {
+ prod, e := newPartitionProducer(p.client, partition, p.options, partitionIdx, p.metrics)
+ c <- ProducerError{
+ partition: partitionIdx,
+ prod: prod,
+ err: e,
+ }
+ }(partitionIdx, partition)
+ }
+
+ for i := 0; i < partitionsToAdd; i++ {
+ pe, ok := <-c
+ if ok {
+ if pe.err != nil {
+ err = pe.err
+ } else {
+ p.producers[pe.partition] = pe.prod
+ }
+ }
+ }
+
+ if err != nil {
+ // Since there were some failures, cleanup all the partitions that succeeded in creating the producers
+ for _, producer := range p.producers {
+ if producer != nil {
+ producer.Close()
+ }
+ }
+ return err
+ }
+
+ if newNumPartitions < oldNumPartitions {
+ p.metrics.ProducersPartitions.Set(float64(newNumPartitions))
+ } else {
+ p.metrics.ProducersPartitions.Add(float64(partitionsToAdd))
+ }
+ atomic.StorePointer(&p.producersPtr, unsafe.Pointer(&p.producers))
+ atomic.StoreUint32(&p.numPartitions, uint32(len(p.producers)))
+ return nil
+}
+
+func (p *producer) Topic() string {
+ return p.topic
+}
+
+func (p *producer) Name() string {
+ p.RLock()
+ defer p.RUnlock()
+
+ return p.producers[0].Name()
+}
+
+func (p *producer) NumPartitions() uint32 {
+ return atomic.LoadUint32(&p.numPartitions)
+}
+
+func (p *producer) Send(ctx context.Context, msg *ProducerMessage) (MessageID, error) {
+ return p.getPartition(msg).Send(ctx, msg)
+}
+
+func (p *producer) SendAsync(ctx context.Context, msg *ProducerMessage,
+ callback func(MessageID, *ProducerMessage, error)) {
+ p.getPartition(msg).SendAsync(ctx, msg, callback)
+}
+
+func (p *producer) getPartition(msg *ProducerMessage) Producer {
+ // Since partitions can only increase, it's ok if the producers list
+ // is updated in between. The numPartition is updated only after the list.
+ partition := p.messageRouter(msg, p)
+ producers := *(*[]Producer)(atomic.LoadPointer(&p.producersPtr))
+ if partition >= len(producers) {
+ // We read the old producers list while the count was already
+ // updated
+ partition %= len(producers)
+ }
+ return producers[partition]
+}
+
+func (p *producer) LastSequenceID() int64 {
+ p.RLock()
+ defer p.RUnlock()
+
+ var maxSeq int64 = -1
+ for _, pp := range p.producers {
+ s := pp.LastSequenceID()
+ if s > maxSeq {
+ maxSeq = s
+ }
+ }
+ return maxSeq
+}
+
+func (p *producer) Flush() error {
+ p.RLock()
+ defer p.RUnlock()
+
+ for _, pp := range p.producers {
+ if err := pp.Flush(); err != nil {
+ return err
+ }
+
+ }
+ return nil
+}
+
+func (p *producer) Close() {
+ p.closeOnce.Do(func() {
+ p.stopDiscovery()
+
+ p.Lock()
+ defer p.Unlock()
+
+ for _, pp := range p.producers {
+ pp.Close()
+ }
+ p.client.handlers.Del(p)
+ p.metrics.ProducersPartitions.Sub(float64(len(p.producers)))
+ p.metrics.ProducersClosed.Inc()
+ })
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/producer_interceptor.go b/vendor/github.com/apache/pulsar-client-go/pulsar/producer_interceptor.go
new file mode 100644
index 00000000..cb2cc152
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/producer_interceptor.go
@@ -0,0 +1,43 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+type ProducerInterceptor interface {
+ // BeforeSend This is called before send the message to the brokers. This method is allowed to modify the
+ BeforeSend(producer Producer, message *ProducerMessage)
+
+ // OnSendAcknowledgement This method is called when the message sent to the broker has been acknowledged,
+ // or when sending the message fails.
+ OnSendAcknowledgement(producer Producer, message *ProducerMessage, msgID MessageID)
+}
+
+type ProducerInterceptors []ProducerInterceptor
+
+func (x ProducerInterceptors) BeforeSend(producer Producer, message *ProducerMessage) {
+ for i := range x {
+ x[i].BeforeSend(producer, message)
+ }
+}
+
+func (x ProducerInterceptors) OnSendAcknowledgement(producer Producer, message *ProducerMessage, msgID MessageID) {
+ for i := range x {
+ x[i].OnSendAcknowledgement(producer, message, msgID)
+ }
+}
+
+var defaultProducerInterceptors = make(ProducerInterceptors, 0)
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/producer_partition.go b/vendor/github.com/apache/pulsar-client-go/pulsar/producer_partition.go
new file mode 100644
index 00000000..744df799
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/producer_partition.go
@@ -0,0 +1,1397 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal/compression"
+ internalcrypto "github.com/apache/pulsar-client-go/pulsar/internal/crypto"
+
+ "google.golang.org/protobuf/proto"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+
+ uAtomic "go.uber.org/atomic"
+)
+
+type producerState int32
+
+const (
+ // producer states
+ producerInit = iota
+ producerReady
+ producerClosing
+ producerClosed
+)
+
+var (
+ errFailAddToBatch = newError(AddToBatchFailed, "message add to batch failed")
+ errSendTimeout = newError(TimeoutError, "message send timeout")
+ errSendQueueIsFull = newError(ProducerQueueIsFull, "producer send queue is full")
+ errContextExpired = newError(TimeoutError, "message send context expired")
+ errMessageTooLarge = newError(MessageTooBig, "message size exceeds MaxMessageSize")
+ errMetaTooLarge = newError(InvalidMessage, "message metadata size exceeds MaxMessageSize")
+ errProducerClosed = newError(ProducerClosed, "producer already been closed")
+ errMemoryBufferIsFull = newError(ClientMemoryBufferIsFull, "client memory buffer is full")
+
+ buffersPool sync.Pool
+)
+
+var errTopicNotFount = "TopicNotFound"
+
+type partitionProducer struct {
+ state uAtomic.Int32
+ client *client
+ topic string
+ log log.Logger
+
+ conn uAtomic.Value
+
+ options *ProducerOptions
+ producerName string
+ userProvidedProducerName bool
+ producerID uint64
+ batchBuilder internal.BatchBuilder
+ sequenceIDGenerator *uint64
+ batchFlushTicker *time.Ticker
+ encryptor internalcrypto.Encryptor
+ compressionProvider compression.Provider
+
+ // Channel where app is posting messages to be published
+ eventsChan chan interface{}
+ closeCh chan struct{}
+ connectClosedCh chan connectionClosed
+
+ publishSemaphore internal.Semaphore
+ pendingQueue internal.BlockingQueue
+ lastSequenceID int64
+ schemaInfo *SchemaInfo
+ partitionIdx int32
+ metrics *internal.LeveledMetrics
+ epoch uint64
+ schemaCache *schemaCache
+ topicEpoch *uint64
+}
+
+type schemaCache struct {
+ lock sync.RWMutex
+ schemas map[string][]byte
+}
+
+func newSchemaCache() *schemaCache {
+ return &schemaCache{
+ schemas: make(map[string][]byte),
+ }
+}
+
+func (s *schemaCache) Put(schema *SchemaInfo, schemaVersion []byte) {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+
+ key := schema.hash()
+ s.schemas[key] = schemaVersion
+}
+
+func (s *schemaCache) Get(schema *SchemaInfo) (schemaVersion []byte) {
+ s.lock.RLock()
+ defer s.lock.RUnlock()
+
+ key := schema.hash()
+ return s.schemas[key]
+}
+func newPartitionProducer(client *client, topic string, options *ProducerOptions, partitionIdx int,
+ metrics *internal.LeveledMetrics) (
+ *partitionProducer, error) {
+ var batchingMaxPublishDelay time.Duration
+ if options.BatchingMaxPublishDelay != 0 {
+ batchingMaxPublishDelay = options.BatchingMaxPublishDelay
+ } else {
+ batchingMaxPublishDelay = defaultBatchingMaxPublishDelay
+ }
+
+ var maxPendingMessages int
+ if options.MaxPendingMessages == 0 {
+ maxPendingMessages = 1000
+ } else {
+ maxPendingMessages = options.MaxPendingMessages
+ }
+
+ logger := client.log.SubLogger(log.Fields{"topic": topic})
+
+ p := &partitionProducer{
+ client: client,
+ topic: topic,
+ log: logger,
+ options: options,
+ producerID: client.rpcClient.NewProducerID(),
+ eventsChan: make(chan interface{}, maxPendingMessages),
+ connectClosedCh: make(chan connectionClosed, 10),
+ closeCh: make(chan struct{}),
+ batchFlushTicker: time.NewTicker(batchingMaxPublishDelay),
+ compressionProvider: internal.GetCompressionProvider(pb.CompressionType(options.CompressionType),
+ compression.Level(options.CompressionLevel)),
+ publishSemaphore: internal.NewSemaphore(int32(maxPendingMessages)),
+ pendingQueue: internal.NewBlockingQueue(maxPendingMessages),
+ lastSequenceID: -1,
+ partitionIdx: int32(partitionIdx),
+ metrics: metrics,
+ epoch: 0,
+ schemaCache: newSchemaCache(),
+ }
+ if p.options.DisableBatching {
+ p.batchFlushTicker.Stop()
+ }
+ p.setProducerState(producerInit)
+
+ if options.Schema != nil && options.Schema.GetSchemaInfo() != nil {
+ p.schemaInfo = options.Schema.GetSchemaInfo()
+ } else {
+ p.schemaInfo = nil
+ }
+
+ if options.Name != "" {
+ p.producerName = options.Name
+ p.userProvidedProducerName = true
+ } else {
+ p.userProvidedProducerName = false
+ }
+ err := p.grabCnx()
+ if err != nil {
+ p.batchFlushTicker.Stop()
+ logger.WithError(err).Error("Failed to create producer at newPartitionProducer")
+ return nil, err
+ }
+
+ p.log = p.log.SubLogger(log.Fields{
+ "producer_name": p.producerName,
+ "producerID": p.producerID,
+ })
+
+ p.log.WithField("cnx", p._getConn().ID()).Info("Created producer")
+ p.setProducerState(producerReady)
+
+ if p.options.SendTimeout > 0 {
+ go p.failTimeoutMessages()
+ }
+
+ go p.runEventsLoop()
+
+ return p, nil
+}
+
+func (p *partitionProducer) grabCnx() error {
+ lr, err := p.client.lookupService.Lookup(p.topic)
+ if err != nil {
+ p.log.WithError(err).Warn("Failed to lookup topic")
+ return err
+ }
+
+ p.log.Debug("Lookup result: ", lr)
+ id := p.client.rpcClient.NewRequestID()
+
+ // set schema info for producer
+
+ var pbSchema *pb.Schema
+ if p.schemaInfo != nil {
+ tmpSchemaType := pb.Schema_Type(int32(p.schemaInfo.Type))
+ pbSchema = &pb.Schema{
+ Name: proto.String(p.schemaInfo.Name),
+ Type: &tmpSchemaType,
+ SchemaData: []byte(p.schemaInfo.Schema),
+ Properties: internal.ConvertFromStringMap(p.schemaInfo.Properties),
+ }
+ p.log.Debugf("The partition producer schema name is: %s", pbSchema.Name)
+ } else {
+ p.log.Debug("The partition producer schema is nil")
+ }
+
+ cmdProducer := &pb.CommandProducer{
+ RequestId: proto.Uint64(id),
+ Topic: proto.String(p.topic),
+ Encrypted: nil,
+ ProducerId: proto.Uint64(p.producerID),
+ Schema: pbSchema,
+ Epoch: proto.Uint64(atomic.LoadUint64(&p.epoch)),
+ UserProvidedProducerName: proto.Bool(p.userProvidedProducerName),
+ ProducerAccessMode: toProtoProducerAccessMode(p.options.ProducerAccessMode).Enum(),
+ }
+
+ if p.topicEpoch != nil {
+ cmdProducer.TopicEpoch = proto.Uint64(*p.topicEpoch)
+ }
+
+ if p.producerName != "" {
+ cmdProducer.ProducerName = proto.String(p.producerName)
+ }
+
+ if len(p.options.Properties) > 0 {
+ cmdProducer.Metadata = toKeyValues(p.options.Properties)
+ }
+ res, err := p.client.rpcClient.Request(lr.LogicalAddr, lr.PhysicalAddr, id, pb.BaseCommand_PRODUCER, cmdProducer)
+ if err != nil {
+ p.log.WithError(err).Error("Failed to create producer at send PRODUCER request")
+ return err
+ }
+
+ p.producerName = res.Response.ProducerSuccess.GetProducerName()
+ nextTopicEpoch := res.Response.ProducerSuccess.GetTopicEpoch()
+ p.topicEpoch = &nextTopicEpoch
+
+ if p.options.Encryption != nil {
+ p.encryptor = internalcrypto.NewProducerEncryptor(p.options.Encryption.Keys,
+ p.options.Encryption.KeyReader,
+ p.options.Encryption.MessageCrypto,
+ p.options.Encryption.ProducerCryptoFailureAction, p.log)
+ } else {
+ p.encryptor = internalcrypto.NewNoopEncryptor()
+ }
+
+ if p.sequenceIDGenerator == nil {
+ nextSequenceID := uint64(res.Response.ProducerSuccess.GetLastSequenceId() + 1)
+ p.sequenceIDGenerator = &nextSequenceID
+ }
+
+ schemaVersion := res.Response.ProducerSuccess.GetSchemaVersion()
+ if len(schemaVersion) != 0 {
+ p.schemaCache.Put(p.schemaInfo, schemaVersion)
+ }
+
+ p._setConn(res.Cnx)
+ err = p._getConn().RegisterListener(p.producerID, p)
+ if err != nil {
+ return err
+ }
+
+ if !p.options.DisableBatching && p.batchBuilder == nil {
+ provider, err := GetBatcherBuilderProvider(p.options.BatcherBuilderType)
+ if err != nil {
+ return err
+ }
+ maxMessageSize := uint32(p._getConn().GetMaxMessageSize())
+ p.batchBuilder, err = provider(p.options.BatchingMaxMessages, p.options.BatchingMaxSize,
+ maxMessageSize, p.producerName, p.producerID, pb.CompressionType(p.options.CompressionType),
+ compression.Level(p.options.CompressionLevel),
+ p,
+ p.log,
+ p.encryptor)
+ if err != nil {
+ return err
+ }
+ }
+
+ p.log.WithFields(log.Fields{
+ "cnx": res.Cnx.ID(),
+ "epoch": atomic.LoadUint64(&p.epoch),
+ }).Info("Connected producer")
+
+ pendingItems := p.pendingQueue.ReadableSlice()
+ viewSize := len(pendingItems)
+ if viewSize > 0 {
+ p.log.Infof("Resending %d pending batches", viewSize)
+ lastViewItem := pendingItems[viewSize-1].(*pendingItem)
+
+ // iterate at most pending items
+ for i := 0; i < viewSize; i++ {
+ item := p.pendingQueue.Poll()
+ if item == nil {
+ continue
+ }
+ pi := item.(*pendingItem)
+ // when resending pending batches, we update the sendAt timestamp and put to the back of queue
+ // to avoid pending item been removed by failTimeoutMessages and cause race condition
+ pi.Lock()
+ pi.sentAt = time.Now()
+ pi.Unlock()
+ p.pendingQueue.Put(pi)
+ p._getConn().WriteData(pi.buffer)
+
+ if pi == lastViewItem {
+ break
+ }
+ }
+ }
+ return nil
+}
+
+type connectionClosed struct{}
+
+func (p *partitionProducer) GetBuffer() internal.Buffer {
+ b, ok := buffersPool.Get().(internal.Buffer)
+ if ok {
+ b.Clear()
+ }
+ return b
+}
+
+func (p *partitionProducer) ConnectionClosed() {
+ // Trigger reconnection in the produce goroutine
+ p.log.WithField("cnx", p._getConn().ID()).Warn("Connection was closed")
+ p.connectClosedCh <- connectionClosed{}
+}
+
+func (p *partitionProducer) getOrCreateSchema(schemaInfo *SchemaInfo) (schemaVersion []byte, err error) {
+
+ tmpSchemaType := pb.Schema_Type(int32(schemaInfo.Type))
+ pbSchema := &pb.Schema{
+ Name: proto.String(schemaInfo.Name),
+ Type: &tmpSchemaType,
+ SchemaData: []byte(schemaInfo.Schema),
+ Properties: internal.ConvertFromStringMap(schemaInfo.Properties),
+ }
+ id := p.client.rpcClient.NewRequestID()
+ req := &pb.CommandGetOrCreateSchema{
+ RequestId: proto.Uint64(id),
+ Topic: proto.String(p.topic),
+ Schema: pbSchema,
+ }
+ res, err := p.client.rpcClient.RequestOnCnx(p._getConn(), id, pb.BaseCommand_GET_OR_CREATE_SCHEMA, req)
+ if err != nil {
+ return
+ }
+ if res.Response.Error != nil {
+ err = errors.New(res.Response.GetError().String())
+ return
+ }
+ if res.Response.GetOrCreateSchemaResponse.ErrorCode != nil {
+ err = errors.New(*res.Response.GetOrCreateSchemaResponse.ErrorMessage)
+ return
+ }
+ return res.Response.GetOrCreateSchemaResponse.SchemaVersion, nil
+}
+
+func (p *partitionProducer) reconnectToBroker() {
+ var maxRetry int
+ if p.options.MaxReconnectToBroker == nil {
+ maxRetry = -1
+ } else {
+ maxRetry = int(*p.options.MaxReconnectToBroker)
+ }
+
+ for maxRetry != 0 {
+ if p.getProducerState() != producerReady {
+ // Producer is already closing
+ p.log.Info("producer state not ready, exit reconnect")
+ return
+ }
+
+ var (
+ delayReconnectTime time.Duration
+ defaultBackoff = internal.DefaultBackoff{}
+ )
+
+ if p.options.BackoffPolicy == nil {
+ delayReconnectTime = defaultBackoff.Next()
+ } else {
+ delayReconnectTime = p.options.BackoffPolicy.Next()
+ }
+ p.log.Info("Reconnecting to broker in ", delayReconnectTime)
+ time.Sleep(delayReconnectTime)
+ atomic.AddUint64(&p.epoch, 1)
+ err := p.grabCnx()
+ if err == nil {
+ // Successfully reconnected
+ p.log.WithField("cnx", p._getConn().ID()).Info("Reconnected producer to broker")
+ return
+ }
+ p.log.WithError(err).Error("Failed to create producer at reconnect")
+ errMsg := err.Error()
+ if strings.Contains(errMsg, errTopicNotFount) {
+ // when topic is deleted, we should give up reconnection.
+ p.log.Warn("Topic Not Found.")
+ break
+ }
+
+ if maxRetry > 0 {
+ maxRetry--
+ }
+ p.metrics.ProducersReconnectFailure.Inc()
+ if maxRetry == 0 || defaultBackoff.IsMaxBackoffReached() {
+ p.metrics.ProducersReconnectMaxRetry.Inc()
+ }
+ }
+}
+
+func (p *partitionProducer) runEventsLoop() {
+ go func() {
+ for {
+ select {
+ case <-p.closeCh:
+ p.log.Info("close producer, exit reconnect")
+ return
+ case <-p.connectClosedCh:
+ p.log.Info("runEventsLoop will reconnect in producer")
+ p.reconnectToBroker()
+ }
+ }
+ }()
+
+ for {
+ select {
+ case i := <-p.eventsChan:
+ switch v := i.(type) {
+ case *sendRequest:
+ p.internalSend(v)
+ case *flushRequest:
+ p.internalFlush(v)
+ case *closeProducer:
+ p.internalClose(v)
+ return
+ }
+ case <-p.batchFlushTicker.C:
+ p.internalFlushCurrentBatch()
+ }
+ }
+}
+
+func (p *partitionProducer) Topic() string {
+ return p.topic
+}
+
+func (p *partitionProducer) Name() string {
+ return p.producerName
+}
+
+func (p *partitionProducer) internalSend(request *sendRequest) {
+ p.log.Debug("Received send request: ", *request.msg)
+
+ msg := request.msg
+
+ // read payload from message
+ uncompressedPayload := msg.Payload
+ uncompressedPayloadSize := int64(len(uncompressedPayload))
+
+ var schemaPayload []byte
+ var err error
+ if msg.Value != nil && msg.Payload != nil {
+ p.log.Error("Can not set Value and Payload both")
+ request.callback(nil, request.msg, errors.New("can not set Value and Payload both"))
+ return
+ }
+
+ // The block chan must be closed when returned with exception
+ defer request.stopBlock()
+ if !p.canAddToQueue(request, uncompressedPayloadSize) {
+ return
+ }
+
+ if p.options.DisableMultiSchema {
+ if msg.Schema != nil && p.options.Schema != nil &&
+ msg.Schema.GetSchemaInfo().hash() != p.options.Schema.GetSchemaInfo().hash() {
+ p.releaseSemaphoreAndMem(uncompressedPayloadSize)
+ request.callback(nil, request.msg, fmt.Errorf("msg schema can not match with producer schema"))
+ p.log.WithError(err).Errorf("The producer %s of the topic %s is disabled the `MultiSchema`", p.producerName, p.topic)
+ return
+ }
+ }
+ var schema Schema
+ var schemaVersion []byte
+ if msg.Schema != nil {
+ schema = msg.Schema
+ } else if p.options.Schema != nil {
+ schema = p.options.Schema
+ }
+ if msg.Value != nil {
+ // payload and schema are mutually exclusive
+ // try to get payload from schema value only if payload is not set
+ if uncompressedPayload == nil && schema != nil {
+ schemaPayload, err = schema.Encode(msg.Value)
+ if err != nil {
+ p.releaseSemaphoreAndMem(uncompressedPayloadSize)
+ request.callback(nil, request.msg, newError(SchemaFailure, err.Error()))
+ p.log.WithError(err).Errorf("Schema encode message failed %s", msg.Value)
+ return
+ }
+ }
+ }
+ if uncompressedPayload == nil {
+ uncompressedPayload = schemaPayload
+ }
+
+ if schema != nil {
+ schemaVersion = p.schemaCache.Get(schema.GetSchemaInfo())
+ if schemaVersion == nil {
+ schemaVersion, err = p.getOrCreateSchema(schema.GetSchemaInfo())
+ if err != nil {
+ p.releaseSemaphoreAndMem(uncompressedPayloadSize)
+ p.log.WithError(err).Error("get schema version fail")
+ request.callback(nil, request.msg, fmt.Errorf("get schema version fail, err: %w", err))
+ return
+ }
+ p.schemaCache.Put(schema.GetSchemaInfo(), schemaVersion)
+ }
+ }
+
+ uncompressedSize := len(uncompressedPayload)
+
+ deliverAt := msg.DeliverAt
+ if msg.DeliverAfter.Nanoseconds() > 0 {
+ deliverAt = time.Now().Add(msg.DeliverAfter)
+ }
+
+ mm := p.genMetadata(msg, uncompressedSize, deliverAt)
+
+ // set default ReplicationClusters when DisableReplication
+ if msg.DisableReplication {
+ msg.ReplicationClusters = []string{"__local__"}
+ }
+
+ sendAsBatch := !p.options.DisableBatching &&
+ msg.ReplicationClusters == nil &&
+ deliverAt.UnixNano() < 0
+
+ // Once the batching is enabled, it can close blockCh early to make block finish
+ if sendAsBatch {
+ request.stopBlock()
+ } else {
+ // update sequence id for metadata, make the size of msgMetadata more accurate
+ // batch sending will update sequence ID in the BatchBuilder
+ p.updateMetadataSeqID(mm, msg)
+ }
+
+ maxMessageSize := int(p._getConn().GetMaxMessageSize())
+
+ // compress payload if not batching
+ var compressedPayload []byte
+ var compressedSize int
+ var checkSize int
+ if !sendAsBatch {
+ compressedPayload = p.compressionProvider.Compress(nil, uncompressedPayload)
+ compressedSize = len(compressedPayload)
+ checkSize = compressedSize
+
+ // set the compress type in msgMetaData
+ compressionType := pb.CompressionType(p.options.CompressionType)
+ if compressionType != pb.CompressionType_NONE {
+ mm.Compression = &compressionType
+ }
+ } else {
+ // final check for batching message is in serializeMessage
+ // this is a double check
+ checkSize = uncompressedSize
+ }
+
+ // if msg is too large and chunking is disabled
+ if checkSize > maxMessageSize && !p.options.EnableChunking {
+ p.releaseSemaphoreAndMem(uncompressedPayloadSize)
+ request.callback(nil, request.msg, errMessageTooLarge)
+ p.log.WithError(errMessageTooLarge).
+ WithField("size", checkSize).
+ WithField("properties", msg.Properties).
+ Errorf("MaxMessageSize %d", maxMessageSize)
+ p.metrics.PublishErrorsMsgTooLarge.Inc()
+ return
+ }
+
+ var totalChunks int
+ // max chunk payload size
+ var payloadChunkSize int
+ if sendAsBatch || !p.options.EnableChunking {
+ totalChunks = 1
+ payloadChunkSize = int(p._getConn().GetMaxMessageSize())
+ } else {
+ payloadChunkSize = int(p._getConn().GetMaxMessageSize()) - proto.Size(mm)
+ if payloadChunkSize <= 0 {
+ p.releaseSemaphoreAndMem(uncompressedPayloadSize)
+ request.callback(nil, msg, errMetaTooLarge)
+ p.log.WithError(errMetaTooLarge).
+ WithField("metadata size", proto.Size(mm)).
+ WithField("properties", msg.Properties).
+ Errorf("MaxMessageSize %d", int(p._getConn().GetMaxMessageSize()))
+ p.metrics.PublishErrorsMsgTooLarge.Inc()
+ return
+ }
+ // set ChunkMaxMessageSize
+ if p.options.ChunkMaxMessageSize != 0 {
+ payloadChunkSize = int(math.Min(float64(payloadChunkSize), float64(p.options.ChunkMaxMessageSize)))
+ }
+ totalChunks = int(math.Max(1, math.Ceil(float64(compressedSize)/float64(payloadChunkSize))))
+ }
+
+ // set total chunks to send request
+ request.totalChunks = totalChunks
+
+ if !sendAsBatch {
+ if totalChunks > 1 {
+ var lhs, rhs int
+ uuid := fmt.Sprintf("%s-%s", p.producerName, strconv.FormatUint(*mm.SequenceId, 10))
+ mm.Uuid = proto.String(uuid)
+ mm.NumChunksFromMsg = proto.Int32(int32(totalChunks))
+ mm.TotalChunkMsgSize = proto.Int32(int32(compressedSize))
+ cr := newChunkRecorder()
+ for chunkID := 0; chunkID < totalChunks; chunkID++ {
+ lhs = chunkID * payloadChunkSize
+ if rhs = lhs + payloadChunkSize; rhs > compressedSize {
+ rhs = compressedSize
+ }
+ // update chunk id
+ mm.ChunkId = proto.Int32(int32(chunkID))
+ nsr := &sendRequest{
+ ctx: request.ctx,
+ msg: request.msg,
+ callback: request.callback,
+ callbackOnce: request.callbackOnce,
+ publishTime: request.publishTime,
+ blockCh: request.blockCh,
+ closeBlockChOnce: request.closeBlockChOnce,
+ totalChunks: totalChunks,
+ chunkID: chunkID,
+ uuid: uuid,
+ chunkRecorder: cr,
+ }
+ // the permit of first chunk has acquired
+ if chunkID != 0 && !p.canAddToQueue(nsr, 0) {
+ p.releaseSemaphoreAndMem(uncompressedPayloadSize - int64(rhs))
+ return
+ }
+ p.internalSingleSend(mm, compressedPayload[lhs:rhs], nsr, uint32(maxMessageSize))
+ }
+ // close the blockCh when all the chunks acquired permits
+ request.stopBlock()
+ } else {
+ // close the blockCh when totalChunks is 1 (it has acquired permits)
+ request.stopBlock()
+ p.internalSingleSend(mm, compressedPayload, request, uint32(maxMessageSize))
+ }
+ } else {
+ smm := p.genSingleMessageMetadataInBatch(msg, uncompressedSize)
+ multiSchemaEnabled := !p.options.DisableMultiSchema
+ added := p.batchBuilder.Add(smm, p.sequenceIDGenerator, uncompressedPayload, request,
+ msg.ReplicationClusters, deliverAt, schemaVersion, multiSchemaEnabled)
+ if !added {
+ // The current batch is full.. flush it and retry
+
+ p.internalFlushCurrentBatch()
+
+ // after flushing try again to add the current payload
+ if ok := p.batchBuilder.Add(smm, p.sequenceIDGenerator, uncompressedPayload, request,
+ msg.ReplicationClusters, deliverAt, schemaVersion, multiSchemaEnabled); !ok {
+ p.releaseSemaphoreAndMem(uncompressedPayloadSize)
+ request.callback(nil, request.msg, errFailAddToBatch)
+ p.log.WithField("size", uncompressedSize).
+ WithField("properties", msg.Properties).
+ Error("unable to add message to batch")
+ return
+ }
+ }
+ if request.flushImmediately {
+
+ p.internalFlushCurrentBatch()
+
+ }
+ }
+}
+
+func (p *partitionProducer) genMetadata(msg *ProducerMessage,
+ uncompressedSize int,
+ deliverAt time.Time) (mm *pb.MessageMetadata) {
+ mm = &pb.MessageMetadata{
+ ProducerName: &p.producerName,
+ PublishTime: proto.Uint64(internal.TimestampMillis(time.Now())),
+ ReplicateTo: msg.ReplicationClusters,
+ UncompressedSize: proto.Uint32(uint32(uncompressedSize)),
+ }
+
+ if msg.Key != "" {
+ mm.PartitionKey = proto.String(msg.Key)
+ }
+
+ if msg.Properties != nil {
+ mm.Properties = internal.ConvertFromStringMap(msg.Properties)
+ }
+
+ if deliverAt.UnixNano() > 0 {
+ mm.DeliverAtTime = proto.Int64(int64(internal.TimestampMillis(deliverAt)))
+ }
+
+ return
+}
+
+func (p *partitionProducer) updateMetadataSeqID(mm *pb.MessageMetadata, msg *ProducerMessage) {
+ if msg.SequenceID != nil {
+ mm.SequenceId = proto.Uint64(uint64(*msg.SequenceID))
+ } else {
+ mm.SequenceId = proto.Uint64(internal.GetAndAdd(p.sequenceIDGenerator, 1))
+ }
+}
+
+func (p *partitionProducer) genSingleMessageMetadataInBatch(msg *ProducerMessage,
+ uncompressedSize int) (smm *pb.SingleMessageMetadata) {
+ smm = &pb.SingleMessageMetadata{
+ PayloadSize: proto.Int32(int32(uncompressedSize)),
+ }
+
+ if !msg.EventTime.IsZero() {
+ smm.EventTime = proto.Uint64(internal.TimestampMillis(msg.EventTime))
+ }
+
+ if msg.Key != "" {
+ smm.PartitionKey = proto.String(msg.Key)
+ }
+
+ if len(msg.OrderingKey) != 0 {
+ smm.OrderingKey = []byte(msg.OrderingKey)
+ }
+
+ if msg.Properties != nil {
+ smm.Properties = internal.ConvertFromStringMap(msg.Properties)
+ }
+
+ var sequenceID uint64
+ if msg.SequenceID != nil {
+ sequenceID = uint64(*msg.SequenceID)
+ } else {
+ sequenceID = internal.GetAndAdd(p.sequenceIDGenerator, 1)
+ }
+
+ smm.SequenceId = proto.Uint64(sequenceID)
+
+ return
+}
+
+func (p *partitionProducer) internalSingleSend(mm *pb.MessageMetadata,
+ compressedPayload []byte,
+ request *sendRequest,
+ maxMessageSize uint32) {
+ msg := request.msg
+
+ payloadBuf := internal.NewBuffer(len(compressedPayload))
+ payloadBuf.Write(compressedPayload)
+
+ buffer := p.GetBuffer()
+ if buffer == nil {
+ buffer = internal.NewBuffer(int(payloadBuf.ReadableBytes() * 3 / 2))
+ }
+
+ sid := *mm.SequenceId
+
+ if err := internal.SingleSend(
+ buffer,
+ p.producerID,
+ sid,
+ mm,
+ payloadBuf,
+ p.encryptor,
+ maxMessageSize,
+ ); err != nil {
+ request.callback(nil, request.msg, err)
+ p.releaseSemaphoreAndMem(int64(len(msg.Payload)))
+ p.log.WithError(err).Errorf("Single message serialize failed %s", msg.Value)
+ return
+ }
+
+ p.pendingQueue.Put(&pendingItem{
+ sentAt: time.Now(),
+ buffer: buffer,
+ sequenceID: sid,
+ sendRequests: []interface{}{request},
+ })
+ p._getConn().WriteData(buffer)
+}
+
+type pendingItem struct {
+ sync.Mutex
+ buffer internal.Buffer
+ sequenceID uint64
+ sentAt time.Time
+ sendRequests []interface{}
+ completed bool
+}
+
+func (p *partitionProducer) internalFlushCurrentBatch() {
+ if p.batchBuilder.IsMultiBatches() {
+ p.internalFlushCurrentBatches()
+ return
+ }
+
+ batchData, sequenceID, callbacks, err := p.batchBuilder.Flush()
+ if batchData == nil {
+ return
+ }
+
+ // error occurred in batch flush
+ // report it using callback
+ if err != nil {
+ for _, cb := range callbacks {
+ if sr, ok := cb.(*sendRequest); ok {
+ sr.callback(nil, sr.msg, err)
+ }
+ }
+ if errors.Is(err, internal.ErrExceedMaxMessageSize) {
+ p.log.WithError(errMessageTooLarge).
+ Errorf("internal err: %s", err)
+ p.metrics.PublishErrorsMsgTooLarge.Inc()
+ return
+ }
+ return
+ }
+
+ p.pendingQueue.Put(&pendingItem{
+ sentAt: time.Now(),
+ buffer: batchData,
+ sequenceID: sequenceID,
+ sendRequests: callbacks,
+ })
+ p._getConn().WriteData(batchData)
+}
+
+func (p *partitionProducer) failTimeoutMessages() {
+ diff := func(sentAt time.Time) time.Duration {
+ return p.options.SendTimeout - time.Since(sentAt)
+ }
+
+ t := time.NewTimer(p.options.SendTimeout)
+ defer t.Stop()
+
+ for range t.C {
+ state := p.getProducerState()
+ if state == producerClosing || state == producerClosed {
+ return
+ }
+
+ item := p.pendingQueue.Peek()
+ if item == nil {
+ // pending queue is empty
+ t.Reset(p.options.SendTimeout)
+ continue
+ }
+ oldestItem := item.(*pendingItem)
+ if nextWaiting := diff(oldestItem.sentAt); nextWaiting > 0 {
+ // none of these pending messages have timed out, wait and retry
+ t.Reset(nextWaiting)
+ continue
+ }
+
+ // since pending queue is not thread safe because of there is no global iteration lock
+ // to control poll from pending queue, current goroutine and connection receipt handler
+ // iterate pending queue at the same time, this maybe a performance trade-off
+ // see https://github.com/apache/pulsar-client-go/pull/301
+ curViewItems := p.pendingQueue.ReadableSlice()
+ viewSize := len(curViewItems)
+ if viewSize <= 0 {
+ // double check
+ t.Reset(p.options.SendTimeout)
+ continue
+ }
+ p.log.Infof("Failing %d messages", viewSize)
+ lastViewItem := curViewItems[viewSize-1].(*pendingItem)
+
+ // iterate at most viewSize items
+ for i := 0; i < viewSize; i++ {
+ tickerNeedWaiting := time.Duration(0)
+ item := p.pendingQueue.CompareAndPoll(
+ func(m interface{}) bool {
+ if m == nil {
+ return false
+ }
+
+ pi := m.(*pendingItem)
+ pi.Lock()
+ defer pi.Unlock()
+ if nextWaiting := diff(pi.sentAt); nextWaiting > 0 {
+ // current and subsequent items not timeout yet, stop iterating
+ tickerNeedWaiting = nextWaiting
+ return false
+ }
+ return true
+ })
+
+ if item == nil {
+ t.Reset(p.options.SendTimeout)
+ break
+ }
+
+ if tickerNeedWaiting > 0 {
+ t.Reset(tickerNeedWaiting)
+ break
+ }
+
+ pi := item.(*pendingItem)
+ pi.Lock()
+
+ for _, i := range pi.sendRequests {
+ sr := i.(*sendRequest)
+ if sr.msg != nil {
+ size := len(sr.msg.Payload)
+ p.releaseSemaphoreAndMem(int64(size))
+ p.metrics.MessagesPending.Dec()
+ p.metrics.BytesPending.Sub(float64(size))
+ p.metrics.PublishErrorsTimeout.Inc()
+ p.log.WithError(errSendTimeout).
+ WithField("size", size).
+ WithField("properties", sr.msg.Properties)
+ }
+
+ if sr.callback != nil {
+ sr.callbackOnce.Do(func() {
+ sr.callback(nil, sr.msg, errSendTimeout)
+ })
+ }
+ }
+
+ // flag the send has completed with error, flush make no effect
+ pi.Complete()
+ pi.Unlock()
+
+ // finally reached the last view item, current iteration ends
+ if pi == lastViewItem {
+ t.Reset(p.options.SendTimeout)
+ break
+ }
+ }
+ }
+}
+
+func (p *partitionProducer) internalFlushCurrentBatches() {
+ batchesData, sequenceIDs, callbacks, errs := p.batchBuilder.FlushBatches()
+ if batchesData == nil {
+ return
+ }
+
+ for i := range batchesData {
+ // error occurred in processing batch
+ // report it using callback
+ if errs[i] != nil {
+ for _, cb := range callbacks[i] {
+ if sr, ok := cb.(*sendRequest); ok {
+ sr.callback(nil, sr.msg, errs[i])
+ }
+ }
+ if errors.Is(errs[i], internal.ErrExceedMaxMessageSize) {
+ p.log.WithError(errMessageTooLarge).
+ Errorf("internal err: %s", errs[i])
+ p.metrics.PublishErrorsMsgTooLarge.Inc()
+ return
+ }
+ continue
+ }
+ if batchesData[i] == nil {
+ continue
+ }
+ p.pendingQueue.Put(&pendingItem{
+ sentAt: time.Now(),
+ buffer: batchesData[i],
+ sequenceID: sequenceIDs[i],
+ sendRequests: callbacks[i],
+ })
+ p._getConn().WriteData(batchesData[i])
+ }
+
+}
+
+func (p *partitionProducer) internalFlush(fr *flushRequest) {
+
+ p.internalFlushCurrentBatch()
+
+ pi, ok := p.pendingQueue.PeekLast().(*pendingItem)
+ if !ok {
+ close(fr.doneCh)
+ return
+ }
+
+ // lock the pending request while adding requests
+ // since the ReceivedSendReceipt func iterates over this list
+ pi.Lock()
+ defer pi.Unlock()
+
+ if pi.completed {
+ // The last item in the queue has been completed while we were
+ // looking at it. It's safe at this point to assume that every
+ // message enqueued before Flush() was called are now persisted
+ close(fr.doneCh)
+ return
+ }
+
+ sendReq := &sendRequest{
+ msg: nil,
+ callback: func(id MessageID, message *ProducerMessage, e error) {
+ fr.err = e
+ close(fr.doneCh)
+ },
+ }
+
+ pi.sendRequests = append(pi.sendRequests, sendReq)
+}
+
+func (p *partitionProducer) Send(ctx context.Context, msg *ProducerMessage) (MessageID, error) {
+ var err error
+ var msgID MessageID
+
+ // use atomic bool to avoid race
+ isDone := uAtomic.NewBool(false)
+ doneCh := make(chan struct{})
+
+ p.internalSendAsync(ctx, msg, func(ID MessageID, message *ProducerMessage, e error) {
+ if isDone.CAS(false, true) {
+ err = e
+ msgID = ID
+ close(doneCh)
+ }
+ }, true)
+
+ // wait for send request to finish
+ <-doneCh
+
+ return msgID, err
+}
+
+func (p *partitionProducer) SendAsync(ctx context.Context, msg *ProducerMessage,
+ callback func(MessageID, *ProducerMessage, error)) {
+ p.internalSendAsync(ctx, msg, callback, false)
+}
+
+func (p *partitionProducer) internalSendAsync(ctx context.Context, msg *ProducerMessage,
+ callback func(MessageID, *ProducerMessage, error), flushImmediately bool) {
+ if p.getProducerState() != producerReady {
+ // Producer is closing
+ callback(nil, msg, errProducerClosed)
+ return
+ }
+
+ // bc only works when DisableBlockIfQueueFull is false
+ bc := make(chan struct{})
+
+ // callbackOnce make sure the callback is only invoked once in chunking
+ callbackOnce := &sync.Once{}
+
+ sr := &sendRequest{
+ ctx: ctx,
+ msg: msg,
+ callback: callback,
+ callbackOnce: callbackOnce,
+ flushImmediately: flushImmediately,
+ publishTime: time.Now(),
+ blockCh: bc,
+ closeBlockChOnce: &sync.Once{},
+ }
+ p.options.Interceptors.BeforeSend(p, msg)
+
+ p.eventsChan <- sr
+
+ if !p.options.DisableBlockIfQueueFull {
+ // block if queue full
+ <-bc
+ }
+}
+
+func (p *partitionProducer) ReceivedSendReceipt(response *pb.CommandSendReceipt) {
+ pi, ok := p.pendingQueue.Peek().(*pendingItem)
+
+ if !ok {
+ // if we receive a receipt although the pending queue is empty, the state of the broker and the producer differs.
+ p.log.Warnf("Got ack %v for timed out msg", response.GetMessageId())
+ return
+ }
+
+ if pi.sequenceID < response.GetSequenceId() {
+ // Force connection closing so that messages can be re-transmitted in a new connection
+ p.log.Warnf("Received ack for %v on sequenceId %v - expected: %v, closing connection", response.GetMessageId(),
+ response.GetSequenceId(), pi.sequenceID)
+ p._getConn().Close()
+ return
+ } else if pi.sequenceID > response.GetSequenceId() {
+ // Ignoring the ack since it's referring to a message that has already timed out.
+ p.log.Warnf("Received ack for %v on sequenceId %v - expected: %v, closing connection", response.GetMessageId(),
+ response.GetSequenceId(), pi.sequenceID)
+ return
+ } else {
+ // The ack was indeed for the expected item in the queue, we can remove it and trigger the callback
+ p.pendingQueue.Poll()
+
+ now := time.Now().UnixNano()
+
+ // lock the pending item while sending the requests
+ pi.Lock()
+ defer pi.Unlock()
+ p.metrics.PublishRPCLatency.Observe(float64(now-pi.sentAt.UnixNano()) / 1.0e9)
+ batchSize := int32(0)
+ for _, i := range pi.sendRequests {
+ sr := i.(*sendRequest)
+ if sr.msg != nil {
+ batchSize = batchSize + 1
+ } else { // Flush request
+ break
+ }
+ }
+ for idx, i := range pi.sendRequests {
+ sr := i.(*sendRequest)
+ if sr.msg != nil {
+ atomic.StoreInt64(&p.lastSequenceID, int64(pi.sequenceID))
+ p.releaseSemaphoreAndMem(int64(len(sr.msg.Payload)))
+ p.metrics.PublishLatency.Observe(float64(now-sr.publishTime.UnixNano()) / 1.0e9)
+ p.metrics.MessagesPublished.Inc()
+ p.metrics.MessagesPending.Dec()
+ payloadSize := float64(len(sr.msg.Payload))
+ p.metrics.BytesPublished.Add(payloadSize)
+ p.metrics.BytesPending.Sub(payloadSize)
+ }
+
+ if sr.callback != nil || len(p.options.Interceptors) > 0 {
+ msgID := newMessageID(
+ int64(response.MessageId.GetLedgerId()),
+ int64(response.MessageId.GetEntryId()),
+ int32(idx),
+ p.partitionIdx,
+ batchSize,
+ )
+
+ if sr.totalChunks > 1 {
+ if sr.chunkID == 0 {
+ sr.chunkRecorder.setFirstChunkID(
+ &messageID{
+ int64(response.MessageId.GetLedgerId()),
+ int64(response.MessageId.GetEntryId()),
+ -1,
+ p.partitionIdx,
+ 0,
+ })
+ } else if sr.chunkID == sr.totalChunks-1 {
+ sr.chunkRecorder.setLastChunkID(
+ &messageID{
+ int64(response.MessageId.GetLedgerId()),
+ int64(response.MessageId.GetEntryId()),
+ -1,
+ p.partitionIdx,
+ 0,
+ })
+ // use chunkMsgID to set msgID
+ msgID = &sr.chunkRecorder.chunkedMsgID
+ }
+ }
+
+ if sr.totalChunks <= 1 || sr.chunkID == sr.totalChunks-1 {
+ if sr.callback != nil {
+ sr.callback(msgID, sr.msg, nil)
+ }
+ p.options.Interceptors.OnSendAcknowledgement(p, sr.msg, msgID)
+ }
+ }
+ }
+
+ // Mark this pending item as done
+ pi.Complete()
+ }
+}
+
+func (p *partitionProducer) internalClose(req *closeProducer) {
+ defer close(req.doneCh)
+ if !p.casProducerState(producerReady, producerClosing) {
+ return
+ }
+
+ p.log.Info("Closing producer")
+
+ id := p.client.rpcClient.NewRequestID()
+ _, err := p.client.rpcClient.RequestOnCnx(p._getConn(), id, pb.BaseCommand_CLOSE_PRODUCER, &pb.CommandCloseProducer{
+ ProducerId: &p.producerID,
+ RequestId: &id,
+ })
+
+ if err != nil {
+ p.log.WithError(err).Warn("Failed to close producer")
+ } else {
+ p.log.Info("Closed producer")
+ }
+
+ if p.batchBuilder != nil {
+ if err = p.batchBuilder.Close(); err != nil {
+ p.log.WithError(err).Warn("Failed to close batch builder")
+ }
+ }
+
+ p.setProducerState(producerClosed)
+ p._getConn().UnregisterListener(p.producerID)
+ p.batchFlushTicker.Stop()
+
+ close(p.closeCh)
+}
+
+func (p *partitionProducer) LastSequenceID() int64 {
+ return atomic.LoadInt64(&p.lastSequenceID)
+}
+
+func (p *partitionProducer) Flush() error {
+ flushReq := &flushRequest{
+ doneCh: make(chan struct{}),
+ err: nil,
+ }
+ p.eventsChan <- flushReq
+
+ // wait for the flush request to complete
+ <-flushReq.doneCh
+ return flushReq.err
+}
+
+func (p *partitionProducer) getProducerState() producerState {
+ return producerState(p.state.Load())
+}
+
+func (p *partitionProducer) setProducerState(state producerState) {
+ p.state.Swap(int32(state))
+}
+
+// set a new consumerState and return the last state
+// returns bool if the new state has been set or not
+func (p *partitionProducer) casProducerState(oldState, newState producerState) bool {
+ return p.state.CAS(int32(oldState), int32(newState))
+}
+
+func (p *partitionProducer) Close() {
+ if p.getProducerState() != producerReady {
+ // Producer is closing
+ return
+ }
+
+ cp := &closeProducer{doneCh: make(chan struct{})}
+ p.eventsChan <- cp
+
+ // wait for close producer request to complete
+ <-cp.doneCh
+}
+
+type sendRequest struct {
+ ctx context.Context
+ msg *ProducerMessage
+ callback func(MessageID, *ProducerMessage, error)
+ callbackOnce *sync.Once
+ publishTime time.Time
+ flushImmediately bool
+ blockCh chan struct{}
+ closeBlockChOnce *sync.Once
+ totalChunks int
+ chunkID int
+ uuid string
+ chunkRecorder *chunkRecorder
+}
+
+// stopBlock can be invoked multiple times safety
+func (sr *sendRequest) stopBlock() {
+ sr.closeBlockChOnce.Do(func() {
+ close(sr.blockCh)
+ })
+}
+
+type closeProducer struct {
+ doneCh chan struct{}
+}
+
+type flushRequest struct {
+ doneCh chan struct{}
+ err error
+}
+
+func (i *pendingItem) Complete() {
+ if i.completed {
+ return
+ }
+ i.completed = true
+ buffersPool.Put(i.buffer)
+}
+
+// _setConn sets the internal connection field of this partition producer atomically.
+// Note: should only be called by this partition producer when a new connection is available.
+func (p *partitionProducer) _setConn(conn internal.Connection) {
+ p.conn.Store(conn)
+}
+
+// _getConn returns internal connection field of this partition producer atomically.
+// Note: should only be called by this partition producer before attempting to use the connection
+func (p *partitionProducer) _getConn() internal.Connection {
+ // Invariant: The conn must be non-nill for the lifetime of the partitionProducer.
+ // For this reason we leave this cast unchecked and panic() if the
+ // invariant is broken
+ return p.conn.Load().(internal.Connection)
+}
+
+func (p *partitionProducer) releaseSemaphoreAndMem(size int64) {
+ p.publishSemaphore.Release()
+ p.client.memLimit.ReleaseMemory(size)
+}
+
+func (p *partitionProducer) canAddToQueue(sr *sendRequest, uncompressedPayloadSize int64) bool {
+ if p.options.DisableBlockIfQueueFull {
+ if !p.publishSemaphore.TryAcquire() {
+ if sr.callback != nil {
+ sr.callback(nil, sr.msg, errSendQueueIsFull)
+ }
+ return false
+ }
+ if !p.client.memLimit.TryReserveMemory(uncompressedPayloadSize) {
+ p.publishSemaphore.Release()
+ if sr.callback != nil {
+ sr.callback(nil, sr.msg, errMemoryBufferIsFull)
+ }
+ return false
+ }
+
+ } else {
+ if !p.publishSemaphore.Acquire(sr.ctx) {
+ sr.callback(nil, sr.msg, errContextExpired)
+ return false
+ }
+ if !p.client.memLimit.ReserveMemory(sr.ctx, uncompressedPayloadSize) {
+ p.publishSemaphore.Release()
+ sr.callback(nil, sr.msg, errContextExpired)
+ return false
+ }
+ }
+ p.metrics.MessagesPending.Inc()
+ p.metrics.BytesPending.Add(float64(len(sr.msg.Payload)))
+ return true
+}
+
+type chunkRecorder struct {
+ chunkedMsgID chunkMessageID
+}
+
+func newChunkRecorder() *chunkRecorder {
+ return &chunkRecorder{
+ chunkedMsgID: chunkMessageID{},
+ }
+}
+
+func (c *chunkRecorder) setFirstChunkID(msgID *messageID) {
+ c.chunkedMsgID.firstChunkID = msgID
+}
+
+func (c *chunkRecorder) setLastChunkID(msgID *messageID) {
+ c.chunkedMsgID.messageID = msgID
+}
+
+func toProtoProducerAccessMode(accessMode ProducerAccessMode) pb.ProducerAccessMode {
+ switch accessMode {
+ case ProducerAccessModeShared:
+ return pb.ProducerAccessMode_Shared
+ case ProducerAccessModeExclusive:
+ return pb.ProducerAccessMode_Exclusive
+ case ProducerAccessModeWaitForExclusive:
+ return pb.ProducerAccessMode_WaitForExclusive
+ }
+
+ return pb.ProducerAccessMode_Shared
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/reader.go b/vendor/github.com/apache/pulsar-client-go/pulsar/reader.go
new file mode 100644
index 00000000..d58d06f6
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/reader.go
@@ -0,0 +1,137 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+)
+
+// ReaderMessage packages Reader and Message as a struct to use.
+type ReaderMessage struct {
+ Reader
+ Message
+}
+
+// ReaderOptions represents Reader options to use.
+type ReaderOptions struct {
+ // Topic specifies the topic this consumer will subscribe on.
+ // This argument is required when constructing the reader.
+ Topic string
+
+ // Name set the reader name.
+ Name string
+
+ // Properties represents a set of application defined properties for the reader.
+ // Those properties will be visible in the topic stats.
+ Properties map[string]string
+
+ // StartMessageID initial reader positioning is done by specifying a message id. The options are:
+ // * `pulsar.EarliestMessage` : Start reading from the earliest message available in the topic
+ // * `pulsar.LatestMessage` : Start reading from the end topic, only getting messages published after the
+ // reader was created
+ // * `MessageID` : Start reading from a particular message id, the reader will position itself on that
+ // specific position. The first message to be read will be the message next to the specified
+ // messageID
+ StartMessageID MessageID
+
+ // StartMessageIDInclusive, if true, the reader will start at the `StartMessageID`, included.
+ // Default is `false` and the reader will start from the "next" message
+ StartMessageIDInclusive bool
+
+ // MessageChannel sets a `MessageChannel` for the consumer
+ // When a message is received, it will be pushed to the channel for consumption
+ MessageChannel chan ReaderMessage
+
+ // ReceiverQueueSize sets the size of the consumer receive queue.
+ // The consumer receive queue controls how many messages can be accumulated by the Reader before the
+ // application calls Reader.readNext(). Using a higher value could potentially increase the consumer
+ // throughput at the expense of bigger memory utilization.
+ // Default value is {@code 1000} messages and should be good for most use cases.
+ ReceiverQueueSize int
+
+ // SubscriptionRolePrefix sets the subscription role prefix. The default prefix is "reader".
+ SubscriptionRolePrefix string
+
+ // SubscriptionName sets the subscription name.
+ // If subscriptionRolePrefix is set at the same time, this configuration will prevail
+ SubscriptionName string
+
+ // ReadCompacted, if enabled, the reader will read messages from the compacted topic rather than reading the
+ // full message backlog of the topic. This means that, if the topic has been compacted, the reader will only
+ // see the latest value for each key in the topic, up until the point in the topic message backlog that has
+ // been compacted. Beyond that point, the messages will be sent as normal.
+ //
+ // ReadCompacted can only be enabled when reading from a persistent topic. Attempting to enable it on non-persistent
+ // topics will lead to the reader create call throwing a PulsarClientException.
+ ReadCompacted bool
+
+ // Decryption represents the encryption related fields required by the reader to decrypt a message.
+ Decryption *MessageDecryptionInfo
+
+ // Schema represents the schema implementation.
+ Schema Schema
+
+ // BackoffPolicy parameterize the following options in the reconnection logic to
+ // allow users to customize the reconnection logic (minBackoff, maxBackoff and jitterPercentage)
+ BackoffPolicy internal.BackoffPolicy
+
+ // MaxPendingChunkedMessage sets the maximum pending chunked messages. (default: 100)
+ MaxPendingChunkedMessage int
+
+ // ExpireTimeOfIncompleteChunk sets the expiry time of discarding incomplete chunked message. (default: 60 seconds)
+ ExpireTimeOfIncompleteChunk time.Duration
+
+ // AutoAckIncompleteChunk sets whether reader auto acknowledges incomplete chunked message when it should
+ // be removed (e.g.the chunked message pending queue is full). (default: false)
+ AutoAckIncompleteChunk bool
+}
+
+// Reader can be used to scan through all the messages currently available in a topic.
+type Reader interface {
+ // Topic from which this reader is reading from
+ Topic() string
+
+ // Next reads the next message in the topic, blocking until a message is available
+ Next(context.Context) (Message, error)
+
+ // HasNext checks if there is any message available to read from the current position
+ HasNext() bool
+
+ // Close the reader and stop the broker to push more messages
+ Close()
+
+ // Seek resets the subscription associated with this reader to a specific message id.
+ // The message id can either be a specific message or represent the first or last messages in the topic.
+ //
+ // Note: this operation can only be done on non-partitioned topics. For these, one can rather perform the
+ // seek() on the individual partitions.
+ Seek(MessageID) error
+
+ // SeekByTime resets the subscription associated with this reader to a specific message publish time.
+ //
+ // Note: this operation can only be done on non-partitioned topics. For these, one can rather perform the seek() on
+ // the individual partitions.
+ //
+ // @param timestamp
+ // the message publish time where to reposition the subscription
+ //
+ SeekByTime(time time.Time) error
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/reader_impl.go b/vendor/github.com/apache/pulsar-client-go/pulsar/reader_impl.go
new file mode 100644
index 00000000..36b492ab
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/reader_impl.go
@@ -0,0 +1,246 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/crypto"
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+const (
+ defaultReceiverQueueSize = 1000
+)
+
+type reader struct {
+ sync.Mutex
+ client *client
+ pc *partitionConsumer
+ messageCh chan ConsumerMessage
+ lastMessageInBroker *trackingMessageID
+ log log.Logger
+ metrics *internal.LeveledMetrics
+}
+
+func newReader(client *client, options ReaderOptions) (Reader, error) {
+ if options.Topic == "" {
+ return nil, newError(InvalidConfiguration, "Topic is required")
+ }
+
+ if options.StartMessageID == nil {
+ return nil, newError(InvalidConfiguration, "StartMessageID is required")
+ }
+
+ var startMessageID *trackingMessageID
+ if !checkMessageIDType(options.StartMessageID) {
+ // a custom type satisfying MessageID may not be a messageID or trackingMessageID
+ // so re-create messageID using its data
+ deserMsgID, err := deserializeMessageID(options.StartMessageID.Serialize())
+ if err != nil {
+ return nil, err
+ }
+ // de-serialized MessageID is a messageID
+ startMessageID = toTrackingMessageID(deserMsgID)
+ } else {
+ startMessageID = toTrackingMessageID(options.StartMessageID)
+ }
+
+ subscriptionName := options.SubscriptionName
+ if subscriptionName == "" {
+ subscriptionName = options.SubscriptionRolePrefix
+ if subscriptionName == "" {
+ subscriptionName = "reader"
+ }
+ subscriptionName += "-" + generateRandomName()
+ }
+
+ receiverQueueSize := options.ReceiverQueueSize
+ if receiverQueueSize <= 0 {
+ receiverQueueSize = defaultReceiverQueueSize
+ }
+
+ // decryption is enabled, use default message crypto if not provided
+ if options.Decryption != nil && options.Decryption.MessageCrypto == nil {
+ messageCrypto, err := crypto.NewDefaultMessageCrypto("decrypt",
+ false,
+ client.log.SubLogger(log.Fields{"topic": options.Topic}))
+ if err != nil {
+ return nil, err
+ }
+ options.Decryption.MessageCrypto = messageCrypto
+ }
+
+ if options.MaxPendingChunkedMessage == 0 {
+ options.MaxPendingChunkedMessage = 100
+ }
+
+ if options.ExpireTimeOfIncompleteChunk == 0 {
+ options.ExpireTimeOfIncompleteChunk = time.Minute
+ }
+
+ consumerOptions := &partitionConsumerOpts{
+ topic: options.Topic,
+ consumerName: options.Name,
+ subscription: subscriptionName,
+ subscriptionType: Exclusive,
+ receiverQueueSize: receiverQueueSize,
+ startMessageID: startMessageID,
+ startMessageIDInclusive: options.StartMessageIDInclusive,
+ subscriptionMode: nonDurable,
+ readCompacted: options.ReadCompacted,
+ metadata: options.Properties,
+ nackRedeliveryDelay: defaultNackRedeliveryDelay,
+ replicateSubscriptionState: false,
+ decryption: options.Decryption,
+ schema: options.Schema,
+ backoffPolicy: options.BackoffPolicy,
+ maxPendingChunkedMessage: options.MaxPendingChunkedMessage,
+ expireTimeOfIncompleteChunk: options.ExpireTimeOfIncompleteChunk,
+ autoAckIncompleteChunk: options.AutoAckIncompleteChunk,
+ }
+
+ reader := &reader{
+ client: client,
+ messageCh: make(chan ConsumerMessage),
+ log: client.log.SubLogger(log.Fields{"topic": options.Topic}),
+ metrics: client.metrics.GetLeveledMetrics(options.Topic),
+ }
+
+ // Provide dummy dlq router with not dlq policy
+ dlq, err := newDlqRouter(client, nil, client.log)
+ if err != nil {
+ return nil, err
+ }
+
+ pc, err := newPartitionConsumer(nil, client, consumerOptions, reader.messageCh, dlq, reader.metrics)
+ if err != nil {
+ close(reader.messageCh)
+ return nil, err
+ }
+
+ reader.pc = pc
+ reader.metrics.ReadersOpened.Inc()
+ return reader, nil
+}
+
+func (r *reader) Topic() string {
+ return r.pc.topic
+}
+
+func (r *reader) Next(ctx context.Context) (Message, error) {
+ for {
+ select {
+ case cm, ok := <-r.messageCh:
+ if !ok {
+ return nil, newError(ConsumerClosed, "consumer closed")
+ }
+
+ // Acknowledge message immediately because the reader is based on non-durable subscription. When it reconnects,
+ // it will specify the subscription position anyway
+ msgID := cm.Message.ID()
+ mid := toTrackingMessageID(msgID)
+ r.pc.lastDequeuedMsg = mid
+ r.pc.AckID(mid)
+ return cm.Message, nil
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+}
+
+func (r *reader) HasNext() bool {
+ if r.lastMessageInBroker != nil && r.hasMoreMessages() {
+ return true
+ }
+
+ for {
+ lastMsgID, err := r.pc.getLastMessageID()
+ if err != nil {
+ r.log.WithError(err).Error("Failed to get last message id from broker")
+ continue
+ } else {
+ r.lastMessageInBroker = lastMsgID
+ break
+ }
+ }
+
+ return r.hasMoreMessages()
+}
+
+func (r *reader) hasMoreMessages() bool {
+ if r.pc.lastDequeuedMsg != nil {
+ return r.lastMessageInBroker.isEntryIDValid() && r.lastMessageInBroker.greater(r.pc.lastDequeuedMsg.messageID)
+ }
+
+ if r.pc.options.startMessageIDInclusive {
+ return r.lastMessageInBroker.isEntryIDValid() &&
+ r.lastMessageInBroker.greaterEqual(r.pc.startMessageID.get().messageID)
+ }
+
+ // Non-inclusive
+ return r.lastMessageInBroker.isEntryIDValid() &&
+ r.lastMessageInBroker.greater(r.pc.startMessageID.get().messageID)
+}
+
+func (r *reader) Close() {
+ r.pc.Close()
+ r.client.handlers.Del(r)
+ r.metrics.ReadersClosed.Inc()
+}
+
+func (r *reader) messageID(msgID MessageID) *trackingMessageID {
+ mid := toTrackingMessageID(msgID)
+
+ partition := int(mid.partitionIdx)
+ // did we receive a valid partition index?
+ if partition < 0 {
+ r.log.Warnf("invalid partition index %d expected", partition)
+ return nil
+ }
+
+ return mid
+}
+
+func (r *reader) Seek(msgID MessageID) error {
+ r.Lock()
+ defer r.Unlock()
+
+ if !checkMessageIDType(msgID) {
+ r.log.Warnf("invalid message id type %T", msgID)
+ return fmt.Errorf("invalid message id type %T", msgID)
+ }
+
+ mid := r.messageID(msgID)
+ if mid == nil {
+ return nil
+ }
+
+ return r.pc.Seek(mid)
+}
+
+func (r *reader) SeekByTime(time time.Time) error {
+ r.Lock()
+ defer r.Unlock()
+
+ return r.pc.SeekByTime(time)
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/retry_router.go b/vendor/github.com/apache/pulsar-client-go/pulsar/retry_router.go
new file mode 100644
index 00000000..75792adc
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/retry_router.go
@@ -0,0 +1,148 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+const (
+ DlqTopicSuffix = "-DLQ"
+ RetryTopicSuffix = "-RETRY"
+ MaxReconsumeTimes = 16
+
+ SysPropertyDelayTime = "DELAY_TIME"
+ SysPropertyRealTopic = "REAL_TOPIC"
+ SysPropertyRetryTopic = "RETRY_TOPIC"
+ SysPropertyReconsumeTimes = "RECONSUMETIMES"
+ SysPropertyOriginMessageID = "ORIGIN_MESSAGE_IDY_TIME"
+ PropertyOriginMessageID = "ORIGIN_MESSAGE_ID"
+)
+
+type RetryMessage struct {
+ producerMsg ProducerMessage
+ consumerMsg ConsumerMessage
+}
+
+type retryRouter struct {
+ client Client
+ producer Producer
+ policy *DLQPolicy
+ messageCh chan RetryMessage
+ closeCh chan interface{}
+ log log.Logger
+}
+
+func newRetryRouter(client Client, policy *DLQPolicy, retryEnabled bool, logger log.Logger) (*retryRouter, error) {
+ r := &retryRouter{
+ client: client,
+ policy: policy,
+ log: logger,
+ }
+
+ if policy != nil && retryEnabled {
+ if policy.MaxDeliveries <= 0 {
+ return nil, newError(InvalidConfiguration, "DLQPolicy.MaxDeliveries needs to be > 0")
+ }
+
+ if policy.RetryLetterTopic == "" {
+ return nil, newError(InvalidConfiguration, "DLQPolicy.RetryLetterTopic needs to be set to a valid topic name")
+ }
+
+ r.messageCh = make(chan RetryMessage)
+ r.closeCh = make(chan interface{}, 1)
+ r.log = logger.SubLogger(log.Fields{"rlq-topic": policy.RetryLetterTopic})
+ go r.run()
+ }
+ return r, nil
+}
+
+func (r *retryRouter) Chan() chan RetryMessage {
+ return r.messageCh
+}
+
+func (r *retryRouter) run() {
+ for {
+ select {
+ case rm := <-r.messageCh:
+ r.log.WithField("msgID", rm.consumerMsg.ID()).Debug("Got message for RLQ")
+ producer := r.getProducer()
+
+ msgID := rm.consumerMsg.ID()
+ producer.SendAsync(context.Background(), &rm.producerMsg, func(messageID MessageID,
+ producerMessage *ProducerMessage, err error) {
+ if err != nil {
+ r.log.WithError(err).WithField("msgID", msgID).Error("Failed to send message to RLQ")
+ rm.consumerMsg.Consumer.Nack(rm.consumerMsg)
+ } else {
+ r.log.WithField("msgID", msgID).Debug("Succeed to send message to RLQ")
+ rm.consumerMsg.Consumer.AckID(msgID)
+ }
+ })
+
+ case <-r.closeCh:
+ if r.producer != nil {
+ r.producer.Close()
+ }
+ r.log.Debug("Closed RLQ router")
+ return
+ }
+ }
+}
+
+func (r *retryRouter) close() {
+ // Attempt to write on the close channel, without blocking
+ select {
+ case r.closeCh <- nil:
+ default:
+ }
+}
+
+func (r *retryRouter) getProducer() Producer {
+ if r.producer != nil {
+ // Producer was already initialized
+ return r.producer
+ }
+
+ // Retry to create producer indefinitely
+ backoff := &internal.DefaultBackoff{}
+ for {
+ opt := r.policy.ProducerOptions
+ opt.Topic = r.policy.RetryLetterTopic
+ // the origin code sets to LZ4 compression with no options
+ // so the new design allows compression type to be overwritten but still set lz4 by default
+ if r.policy.ProducerOptions.CompressionType == NoCompression {
+ opt.CompressionType = LZ4
+ }
+
+ producer, err := r.client.CreateProducer(opt)
+
+ if err != nil {
+ r.log.WithError(err).Error("Failed to create RLQ producer")
+ time.Sleep(backoff.Next())
+ continue
+ } else {
+ r.producer = producer
+ return producer
+ }
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/schema.go b/vendor/github.com/apache/pulsar-client-go/pulsar/schema.go
new file mode 100644
index 00000000..997d85fb
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/schema.go
@@ -0,0 +1,570 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "unsafe"
+
+ log "github.com/sirupsen/logrus"
+
+ "github.com/linkedin/goavro/v2"
+ "google.golang.org/protobuf/proto"
+)
+
+type SchemaType int
+
+const (
+ NONE SchemaType = iota //No schema defined
+ STRING //Simple String encoding with UTF-8
+ JSON //JSON object encoding and validation
+ PROTOBUF //Protobuf message encoding and decoding
+ AVRO //Serialize and deserialize via Avro
+ BOOLEAN //
+ INT8 //A 8-byte integer.
+ INT16 //A 16-byte integer.
+ INT32 //A 32-byte integer.
+ INT64 //A 64-byte integer.
+ FLOAT //A float number.
+ DOUBLE //A double number
+ _ //
+ _ //
+ _ //
+ KeyValue //A Schema that contains Key Schema and Value Schema.
+ BYTES = -1 //A bytes array.
+ AUTO = -2 //
+ AutoConsume = -3 //Auto Consume Type.
+ AutoPublish = -4 // Auto Publish Type.
+)
+
+// Encapsulates data around the schema definition
+type SchemaInfo struct {
+ Name string
+ Schema string
+ Type SchemaType
+ Properties map[string]string
+}
+
+func (s SchemaInfo) hash() string {
+ h := sha256.New()
+ h.Write([]byte(s.Schema))
+ return hex.EncodeToString(h.Sum(nil))
+}
+
+type Schema interface {
+ Encode(v interface{}) ([]byte, error)
+ Decode(data []byte, v interface{}) error
+ Validate(message []byte) error
+ GetSchemaInfo() *SchemaInfo
+}
+
+func NewSchema(schemaType SchemaType, schemaData []byte, properties map[string]string) (schema Schema, err error) {
+ var schemaDef = string(schemaData)
+ var s Schema
+ switch schemaType {
+ case STRING:
+ s = NewStringSchema(properties)
+ case JSON:
+ s = NewJSONSchema(schemaDef, properties)
+ case PROTOBUF:
+ s = NewProtoSchema(schemaDef, properties)
+ case AVRO:
+ s = NewAvroSchema(schemaDef, properties)
+ case INT8:
+ s = NewInt8Schema(properties)
+ case INT16:
+ s = NewInt16Schema(properties)
+ case INT32:
+ s = NewInt32Schema(properties)
+ case INT64:
+ s = NewInt64Schema(properties)
+ case FLOAT:
+ s = NewFloatSchema(properties)
+ case DOUBLE:
+ s = NewDoubleSchema(properties)
+ default:
+ err = fmt.Errorf("not support schema type of %v", schemaType)
+ }
+ schema = s
+ return
+}
+
+type AvroCodec struct {
+ Codec *goavro.Codec
+}
+
+func NewSchemaDefinition(schema *goavro.Codec) *AvroCodec {
+ schemaDef := &AvroCodec{
+ Codec: schema,
+ }
+ return schemaDef
+}
+
+// initAvroCodec returns a Codec used to translate between a byte slice of either
+// binary or textual Avro data and native Go data.
+func initAvroCodec(codec string) (*goavro.Codec, error) {
+ return goavro.NewCodec(codec)
+}
+
+type JSONSchema struct {
+ AvroCodec
+ SchemaInfo
+}
+
+// NewJSONSchema creates a new JSONSchema
+// Note: the function will panic if creation of codec fails
+func NewJSONSchema(jsonAvroSchemaDef string, properties map[string]string) *JSONSchema {
+ js, err := NewJSONSchemaWithValidation(jsonAvroSchemaDef, properties)
+ if err != nil {
+ log.Fatalf("JSONSchema init codec error:%v", err)
+ }
+ return js
+}
+
+// NewJSONSchemaWithValidation creates a new JSONSchema and error to indicate codec failure
+func NewJSONSchemaWithValidation(jsonAvroSchemaDef string, properties map[string]string) (*JSONSchema, error) {
+ js := new(JSONSchema)
+ avroCodec, err := initAvroCodec(jsonAvroSchemaDef)
+ if err != nil {
+ return nil, err
+ }
+ schemaDef := NewSchemaDefinition(avroCodec)
+ js.SchemaInfo.Schema = schemaDef.Codec.Schema()
+ js.SchemaInfo.Type = JSON
+ js.SchemaInfo.Properties = properties
+ js.SchemaInfo.Name = "JSON"
+ return js, nil
+}
+
+func (js *JSONSchema) Encode(data interface{}) ([]byte, error) {
+ return json.Marshal(data)
+}
+
+func (js *JSONSchema) Decode(data []byte, v interface{}) error {
+ return json.Unmarshal(data, v)
+}
+
+func (js *JSONSchema) Validate(message []byte) error {
+ return js.Decode(message, nil)
+}
+
+func (js *JSONSchema) GetSchemaInfo() *SchemaInfo {
+ return &js.SchemaInfo
+}
+
+type ProtoSchema struct {
+ AvroCodec
+ SchemaInfo
+}
+
+// NewProtoSchema creates a new ProtoSchema
+// Note: the function will panic if creation of codec fails
+func NewProtoSchema(protoAvroSchemaDef string, properties map[string]string) *ProtoSchema {
+ ps, err := NewProtoSchemaWithValidation(protoAvroSchemaDef, properties)
+ if err != nil {
+ log.Fatalf("ProtoSchema init codec error:%v", err)
+ }
+ return ps
+}
+
+// NewProtoSchemaWithValidation creates a new ProtoSchema and error to indicate codec failure
+func NewProtoSchemaWithValidation(protoAvroSchemaDef string, properties map[string]string) (*ProtoSchema, error) {
+ ps := new(ProtoSchema)
+ avroCodec, err := initAvroCodec(protoAvroSchemaDef)
+ if err != nil {
+ return nil, err
+ }
+ schemaDef := NewSchemaDefinition(avroCodec)
+ ps.AvroCodec.Codec = schemaDef.Codec
+ ps.SchemaInfo.Schema = schemaDef.Codec.Schema()
+ ps.SchemaInfo.Type = PROTOBUF
+ ps.SchemaInfo.Properties = properties
+ ps.SchemaInfo.Name = "Proto"
+ return ps, nil
+}
+
+func (ps *ProtoSchema) Encode(data interface{}) ([]byte, error) {
+ return proto.Marshal(data.(proto.Message))
+}
+
+func (ps *ProtoSchema) Decode(data []byte, v interface{}) error {
+ return proto.Unmarshal(data, v.(proto.Message))
+}
+
+func (ps *ProtoSchema) Validate(message []byte) error {
+ return ps.Decode(message, nil)
+}
+
+func (ps *ProtoSchema) GetSchemaInfo() *SchemaInfo {
+ return &ps.SchemaInfo
+}
+
+type AvroSchema struct {
+ AvroCodec
+ SchemaInfo
+}
+
+// NewAvroSchema creates a new AvroSchema
+// Note: the function will panic if creation of codec fails
+func NewAvroSchema(avroSchemaDef string, properties map[string]string) *AvroSchema {
+ ps, err := NewAvroSchemaWithValidation(avroSchemaDef, properties)
+ if err != nil {
+ log.Fatalf("AvroSchema init codec error:%v", err)
+ }
+ return ps
+}
+
+// NewAvroSchemaWithValidation creates a new AvroSchema and error to indicate codec failure
+func NewAvroSchemaWithValidation(avroSchemaDef string, properties map[string]string) (*AvroSchema, error) {
+ as := new(AvroSchema)
+ avroCodec, err := initAvroCodec(avroSchemaDef)
+ if err != nil {
+ return nil, err
+ }
+ schemaDef := NewSchemaDefinition(avroCodec)
+ as.AvroCodec.Codec = schemaDef.Codec
+ as.SchemaInfo.Schema = schemaDef.Codec.Schema()
+ as.SchemaInfo.Type = AVRO
+ as.SchemaInfo.Name = "Avro"
+ as.SchemaInfo.Properties = properties
+ return as, nil
+}
+
+func (as *AvroSchema) Encode(data interface{}) ([]byte, error) {
+ textual, err := json.Marshal(data)
+ if err != nil {
+ log.Errorf("serialize data error:%s", err.Error())
+ return nil, err
+ }
+ native, _, err := as.Codec.NativeFromTextual(textual)
+ if err != nil {
+ log.Errorf("convert native Go form to binary Avro data error:%s", err.Error())
+ return nil, err
+ }
+ return as.Codec.BinaryFromNative(nil, native)
+}
+
+func (as *AvroSchema) Decode(data []byte, v interface{}) error {
+ native, _, err := as.Codec.NativeFromBinary(data)
+ if err != nil {
+ log.Errorf("convert binary Avro data back to native Go form error:%s", err.Error())
+ return err
+ }
+ textual, err := as.Codec.TextualFromNative(nil, native)
+ if err != nil {
+ log.Errorf("convert native Go form to textual Avro data error:%s", err.Error())
+ return err
+ }
+ err = json.Unmarshal(textual, v)
+ if err != nil {
+ log.Errorf("unSerialize textual error:%s", err.Error())
+ return err
+ }
+ return nil
+}
+
+func (as *AvroSchema) Validate(message []byte) error {
+ return as.Decode(message, nil)
+}
+
+func (as *AvroSchema) GetSchemaInfo() *SchemaInfo {
+ return &as.SchemaInfo
+}
+
+type StringSchema struct {
+ SchemaInfo
+}
+
+func NewStringSchema(properties map[string]string) *StringSchema {
+ strSchema := new(StringSchema)
+ strSchema.SchemaInfo.Properties = properties
+ strSchema.SchemaInfo.Name = "String"
+ strSchema.SchemaInfo.Type = STRING
+ strSchema.SchemaInfo.Schema = ""
+ return strSchema
+}
+
+func (ss *StringSchema) Encode(v interface{}) ([]byte, error) {
+ return []byte(v.(string)), nil
+}
+
+// Decode convert from byte slice to string without allocating a new string
+func (ss *StringSchema) Decode(data []byte, v interface{}) error {
+ strPtr := (*string)(unsafe.Pointer(&data))
+ reflect.ValueOf(v).Elem().Set(reflect.ValueOf(strPtr))
+ return nil
+}
+
+func (ss *StringSchema) Validate(message []byte) error {
+ return ss.Decode(message, nil)
+}
+
+func (ss *StringSchema) GetSchemaInfo() *SchemaInfo {
+ return &ss.SchemaInfo
+}
+
+type BytesSchema struct {
+ SchemaInfo
+}
+
+func NewBytesSchema(properties map[string]string) *BytesSchema {
+ bytesSchema := new(BytesSchema)
+ bytesSchema.SchemaInfo.Properties = properties
+ bytesSchema.SchemaInfo.Name = "Bytes"
+ bytesSchema.SchemaInfo.Type = BYTES
+ bytesSchema.SchemaInfo.Schema = ""
+ return bytesSchema
+}
+
+func (bs *BytesSchema) Encode(data interface{}) ([]byte, error) {
+ return data.([]byte), nil
+}
+
+func (bs *BytesSchema) Decode(data []byte, v interface{}) error {
+ reflect.ValueOf(v).Elem().Set(reflect.ValueOf(data))
+ return nil
+}
+
+func (bs *BytesSchema) Validate(message []byte) error {
+ return bs.Decode(message, nil)
+}
+
+func (bs *BytesSchema) GetSchemaInfo() *SchemaInfo {
+ return &bs.SchemaInfo
+}
+
+type Int8Schema struct {
+ SchemaInfo
+}
+
+func NewInt8Schema(properties map[string]string) *Int8Schema {
+ int8Schema := new(Int8Schema)
+ int8Schema.SchemaInfo.Properties = properties
+ int8Schema.SchemaInfo.Schema = ""
+ int8Schema.SchemaInfo.Type = INT8
+ int8Schema.SchemaInfo.Name = "INT8"
+ return int8Schema
+}
+
+func (is8 *Int8Schema) Encode(value interface{}) ([]byte, error) {
+ var buf bytes.Buffer
+ err := WriteElements(&buf, value.(int8))
+ return buf.Bytes(), err
+}
+
+func (is8 *Int8Schema) Decode(data []byte, v interface{}) error {
+ buf := bytes.NewReader(data)
+ return ReadElements(buf, v)
+}
+
+func (is8 *Int8Schema) Validate(message []byte) error {
+ if len(message) != 1 {
+ return newError(InvalidMessage, "size of data received by Int8Schema is not 1")
+ }
+ return nil
+}
+
+func (is8 *Int8Schema) GetSchemaInfo() *SchemaInfo {
+ return &is8.SchemaInfo
+}
+
+type Int16Schema struct {
+ SchemaInfo
+}
+
+func NewInt16Schema(properties map[string]string) *Int16Schema {
+ int16Schema := new(Int16Schema)
+ int16Schema.SchemaInfo.Properties = properties
+ int16Schema.SchemaInfo.Name = "INT16"
+ int16Schema.SchemaInfo.Type = INT16
+ int16Schema.SchemaInfo.Schema = ""
+ return int16Schema
+}
+
+func (is16 *Int16Schema) Encode(value interface{}) ([]byte, error) {
+ var buf bytes.Buffer
+ err := WriteElements(&buf, value.(int16))
+ return buf.Bytes(), err
+}
+
+func (is16 *Int16Schema) Decode(data []byte, v interface{}) error {
+ buf := bytes.NewReader(data)
+ return ReadElements(buf, v)
+}
+
+func (is16 *Int16Schema) Validate(message []byte) error {
+ if len(message) != 2 {
+ return newError(InvalidMessage, "size of data received by Int16Schema is not 2")
+ }
+ return nil
+}
+
+func (is16 *Int16Schema) GetSchemaInfo() *SchemaInfo {
+ return &is16.SchemaInfo
+}
+
+type Int32Schema struct {
+ SchemaInfo
+}
+
+func NewInt32Schema(properties map[string]string) *Int32Schema {
+ int32Schema := new(Int32Schema)
+ int32Schema.SchemaInfo.Properties = properties
+ int32Schema.SchemaInfo.Schema = ""
+ int32Schema.SchemaInfo.Name = "INT32"
+ int32Schema.SchemaInfo.Type = INT32
+ return int32Schema
+}
+
+func (is32 *Int32Schema) Encode(value interface{}) ([]byte, error) {
+ var buf bytes.Buffer
+ err := WriteElements(&buf, value.(int32))
+ return buf.Bytes(), err
+}
+
+func (is32 *Int32Schema) Decode(data []byte, v interface{}) error {
+ buf := bytes.NewReader(data)
+ return ReadElements(buf, v)
+}
+
+func (is32 *Int32Schema) Validate(message []byte) error {
+ if len(message) != 4 {
+ return newError(InvalidMessage, "size of data received by Int32Schema is not 4")
+ }
+ return nil
+}
+
+func (is32 *Int32Schema) GetSchemaInfo() *SchemaInfo {
+ return &is32.SchemaInfo
+}
+
+type Int64Schema struct {
+ SchemaInfo
+}
+
+func NewInt64Schema(properties map[string]string) *Int64Schema {
+ int64Schema := new(Int64Schema)
+ int64Schema.SchemaInfo.Properties = properties
+ int64Schema.SchemaInfo.Name = "INT64"
+ int64Schema.SchemaInfo.Type = INT64
+ int64Schema.SchemaInfo.Schema = ""
+ return int64Schema
+}
+
+func (is64 *Int64Schema) Encode(value interface{}) ([]byte, error) {
+ var buf bytes.Buffer
+ err := WriteElements(&buf, value.(int64))
+ return buf.Bytes(), err
+}
+
+func (is64 *Int64Schema) Decode(data []byte, v interface{}) error {
+ buf := bytes.NewReader(data)
+ return ReadElements(buf, v)
+}
+
+func (is64 *Int64Schema) Validate(message []byte) error {
+ if len(message) != 8 {
+ return newError(InvalidMessage, "size of data received by Int64Schema is not 8")
+ }
+ return nil
+}
+
+func (is64 *Int64Schema) GetSchemaInfo() *SchemaInfo {
+ return &is64.SchemaInfo
+}
+
+type FloatSchema struct {
+ SchemaInfo
+}
+
+func NewFloatSchema(properties map[string]string) *FloatSchema {
+ floatSchema := new(FloatSchema)
+ floatSchema.SchemaInfo.Properties = properties
+ floatSchema.SchemaInfo.Type = FLOAT
+ floatSchema.SchemaInfo.Name = "FLOAT"
+ floatSchema.SchemaInfo.Schema = ""
+ return floatSchema
+}
+
+func (fs *FloatSchema) Encode(value interface{}) ([]byte, error) {
+ return BinarySerializer.PutFloat(value)
+}
+
+func (fs *FloatSchema) Decode(data []byte, v interface{}) error {
+ floatValue, err := BinarySerializer.Float32(data)
+ if err != nil {
+ log.Errorf("unSerialize float error:%s", err.Error())
+ return err
+ }
+ reflect.ValueOf(v).Elem().Set(reflect.ValueOf(floatValue))
+ return nil
+}
+
+func (fs *FloatSchema) Validate(message []byte) error {
+ if len(message) != 4 {
+ return newError(InvalidMessage, "size of data received by FloatSchema is not 4")
+ }
+ return nil
+}
+
+func (fs *FloatSchema) GetSchemaInfo() *SchemaInfo {
+ return &fs.SchemaInfo
+}
+
+type DoubleSchema struct {
+ SchemaInfo
+}
+
+func NewDoubleSchema(properties map[string]string) *DoubleSchema {
+ doubleSchema := new(DoubleSchema)
+ doubleSchema.SchemaInfo.Properties = properties
+ doubleSchema.SchemaInfo.Type = DOUBLE
+ doubleSchema.SchemaInfo.Name = "DOUBLE"
+ doubleSchema.SchemaInfo.Schema = ""
+ return doubleSchema
+}
+
+func (ds *DoubleSchema) Encode(value interface{}) ([]byte, error) {
+ return BinarySerializer.PutDouble(value)
+}
+
+func (ds *DoubleSchema) Decode(data []byte, v interface{}) error {
+ doubleValue, err := BinarySerializer.Float64(data)
+ if err != nil {
+ log.Errorf("unSerialize double value error:%s", err.Error())
+ return err
+ }
+ reflect.ValueOf(v).Elem().Set(reflect.ValueOf(doubleValue))
+ return nil
+}
+
+func (ds *DoubleSchema) Validate(message []byte) error {
+ if len(message) != 8 {
+ return newError(InvalidMessage, "size of data received by DoubleSchema is not 8")
+ }
+ return nil
+}
+
+func (ds *DoubleSchema) GetSchemaInfo() *SchemaInfo {
+ return &ds.SchemaInfo
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/table_view.go b/vendor/github.com/apache/pulsar-client-go/pulsar/table_view.go
new file mode 100644
index 00000000..e566bf0b
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/table_view.go
@@ -0,0 +1,78 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "reflect"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+// TableViewOptions contains the options for creating a TableView
+type TableViewOptions struct {
+ // Topic specifies the topic this table view will subscribe on.
+ // This argument is required when constructing the table view.
+ Topic string
+
+ // Set the interval of updating partitions. Default to 1 minute.
+ AutoUpdatePartitionsInterval time.Duration
+
+ // Schema represents the schema implementation.
+ Schema Schema
+
+ // SchemaValueType represents the type of values for the given schema.
+ SchemaValueType reflect.Type
+
+ // Configure the logger used by the TableView.
+ // By default, a wrapped logrus.StandardLogger will be used, namely,
+ // log.NewLoggerWithLogrus(logrus.StandardLogger())
+ Logger log.Logger
+}
+
+// TableView provides a key-value map view of a compacted topic. Messages without keys will be ignored.
+type TableView interface {
+ // Size returns the number of key-value mappings in the TableView.
+ Size() int
+
+ // IsEmpty returns true if this TableView contains no key-value mappings.
+ IsEmpty() bool
+
+ // ContainsKey returns true if this TableView contains a mapping for the specified key.
+ ContainsKey(key string) bool
+
+ // Get returns the value to which the specified key is mapped, or nil if this map contains no mapping for the key.
+ Get(key string) interface{}
+
+ // Entries returns a map view of the mappings contained in this TableView.
+ Entries() map[string]interface{}
+
+ // Keys returns a slice of the keys contained in this TableView.
+ Keys() []string
+
+ // ForEach performs the give action for each entry in this map until all entries have been processed or the action
+ // returns an error.
+ ForEach(func(string, interface{}) error) error
+
+ // ForEachAndListen performs the give action for each entry in this map until all entries have been processed or
+ // the action returns an error.
+ ForEachAndListen(func(string, interface{}) error) error
+
+ // Close closes the table view and releases resources allocated.
+ Close()
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/table_view_impl.go b/vendor/github.com/apache/pulsar-client-go/pulsar/table_view_impl.go
new file mode 100644
index 00000000..85499f19
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/table_view_impl.go
@@ -0,0 +1,277 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "reflect"
+ "sync"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/log"
+ "github.com/sirupsen/logrus"
+)
+
+type cancelReader struct {
+ reader Reader
+ cancelFunc context.CancelFunc
+}
+
+type TableViewImpl struct {
+ client *client
+ options TableViewOptions
+
+ dataMu sync.Mutex
+ data map[string]interface{}
+
+ readersMu sync.Mutex
+ cancelRaders map[string]cancelReader
+
+ listenersMu sync.Mutex
+ listeners []func(string, interface{}) error
+
+ logger log.Logger
+ closed bool
+ closedCh chan struct{}
+}
+
+func newTableView(client *client, options TableViewOptions) (TableView, error) {
+ if options.Topic == "" {
+ return nil, newError(TopicNotFound, "topic is required")
+ }
+
+ if options.Schema != nil && options.SchemaValueType == nil {
+ return nil, newError(InvalidConfiguration, "SchemaValueType is required when Schema is present")
+ }
+
+ var logger log.Logger
+ if options.Logger != nil {
+ logger = options.Logger
+ } else {
+ logger = log.NewLoggerWithLogrus(logrus.StandardLogger())
+ }
+
+ if options.AutoUpdatePartitionsInterval == 0 {
+ options.AutoUpdatePartitionsInterval = time.Minute
+ }
+
+ tv := TableViewImpl{
+ client: client,
+ options: options,
+ data: make(map[string]interface{}),
+ cancelRaders: make(map[string]cancelReader),
+ logger: logger,
+ closedCh: make(chan struct{}),
+ }
+
+ // Do an initial round of partition update check to make sure we can populate the partition readers
+ if err := tv.partitionUpdateCheck(); err != nil {
+ return nil, err
+ }
+ go tv.periodicPartitionUpdateCheck()
+
+ return &tv, nil
+}
+
+func (tv *TableViewImpl) partitionUpdateCheck() error {
+ partitionsArray, err := tv.client.TopicPartitions(tv.options.Topic)
+ if err != nil {
+ return fmt.Errorf("tv.client.TopicPartitions(%s) failed: %w", tv.options.Topic, err)
+ }
+
+ partitions := make(map[string]bool, len(partitionsArray))
+ for _, partition := range partitionsArray {
+ partitions[partition] = true
+ }
+
+ tv.readersMu.Lock()
+ defer tv.readersMu.Unlock()
+
+ for partition, cancelReader := range tv.cancelRaders {
+ if _, ok := partitions[partition]; !ok {
+ cancelReader.cancelFunc()
+ cancelReader.reader.Close()
+ delete(tv.cancelRaders, partition)
+ }
+ }
+
+ for partition := range partitions {
+ if _, ok := tv.cancelRaders[partition]; !ok {
+ reader, err := newReader(tv.client, ReaderOptions{
+ Topic: partition,
+ StartMessageID: EarliestMessageID(),
+ ReadCompacted: true,
+ // TODO: Pooling?
+ Schema: tv.options.Schema,
+ })
+ if err != nil {
+ return fmt.Errorf("create new reader failed for %s: %w", partition, err)
+ }
+ for reader.HasNext() {
+ msg, err := reader.Next(context.Background())
+ if err != nil {
+ tv.logger.Errorf("read next message failed for %s: %w", partition, err)
+ }
+ tv.handleMessage(msg)
+ }
+ ctx, cancelFunc := context.WithCancel(context.Background())
+ tv.cancelRaders[partition] = cancelReader{
+ reader: reader,
+ cancelFunc: cancelFunc,
+ }
+ go tv.watchReaderForNewMessages(ctx, reader)
+ }
+ }
+
+ return nil
+}
+
+func (tv *TableViewImpl) periodicPartitionUpdateCheck() {
+ for {
+ if err := tv.partitionUpdateCheck(); err != nil {
+ tv.logger.Errorf("failed to check for changes in number of partitions: %w", err)
+ }
+ select {
+ case <-tv.closedCh:
+ // If the TableViewImpl has been closed, stop checking for partition updates
+ return
+ case <-time.After(tv.options.AutoUpdatePartitionsInterval):
+ continue
+ }
+ }
+}
+
+func (tv *TableViewImpl) Size() int {
+ tv.dataMu.Lock()
+ defer tv.dataMu.Unlock()
+ return len(tv.data)
+}
+
+func (tv *TableViewImpl) IsEmpty() bool {
+ tv.dataMu.Lock()
+ defer tv.dataMu.Unlock()
+ return tv.Size() == 0
+}
+
+func (tv *TableViewImpl) ContainsKey(key string) bool {
+ tv.dataMu.Lock()
+ defer tv.dataMu.Unlock()
+ _, ok := tv.data[key]
+ return ok
+}
+
+func (tv *TableViewImpl) Get(key string) interface{} {
+ tv.dataMu.Lock()
+ defer tv.dataMu.Unlock()
+ return tv.data[key]
+}
+
+func (tv *TableViewImpl) Entries() map[string]interface{} {
+ tv.dataMu.Lock()
+ defer tv.dataMu.Unlock()
+ data := make(map[string]interface{}, len(tv.data))
+ for k, v := range tv.data {
+ data[k] = v
+ }
+ return tv.data
+}
+
+func (tv *TableViewImpl) Keys() []string {
+ tv.dataMu.Lock()
+ defer tv.dataMu.Unlock()
+ keys := make([]string, len(tv.data))
+ i := 0
+ for k := range tv.data {
+ keys[i] = k
+ i++
+ }
+ return keys
+}
+
+func (tv *TableViewImpl) ForEach(action func(string, interface{}) error) error {
+ tv.dataMu.Lock()
+ defer tv.dataMu.Unlock()
+ for k, v := range tv.data {
+ if err := action(k, v); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (tv *TableViewImpl) ForEachAndListen(action func(string, interface{}) error) error {
+ tv.listenersMu.Lock()
+ defer tv.listenersMu.Unlock()
+
+ if err := tv.ForEach(action); err != nil {
+ return err
+ }
+
+ tv.listeners = append(tv.listeners, action)
+ return nil
+}
+
+func (tv *TableViewImpl) Close() {
+ tv.readersMu.Lock()
+ defer tv.readersMu.Unlock()
+
+ if !tv.closed {
+ tv.closed = true
+ for _, cancelReader := range tv.cancelRaders {
+ cancelReader.reader.Close()
+ }
+ close(tv.closedCh)
+ }
+}
+
+func (tv *TableViewImpl) handleMessage(msg Message) {
+ tv.dataMu.Lock()
+ defer tv.dataMu.Unlock()
+
+ var payload interface{}
+ if len(msg.Payload()) == 0 {
+ delete(tv.data, msg.Key())
+ } else {
+ payload = reflect.Indirect(reflect.New(tv.options.SchemaValueType)).Interface()
+ if err := msg.GetSchemaValue(&payload); err != nil {
+ tv.logger.Errorf("msg.GetSchemaValue() failed with %w; msg is %v", msg, err)
+ }
+ tv.data[msg.Key()] = payload
+ }
+
+ for _, listener := range tv.listeners {
+ if err := listener(msg.Key(), payload); err != nil {
+ tv.logger.Errorf("table view listener failed for %v: %w", msg, err)
+ }
+ }
+}
+
+func (tv *TableViewImpl) watchReaderForNewMessages(ctx context.Context, reader Reader) {
+ for {
+ msg, err := reader.Next(ctx)
+ if err != nil {
+ tv.logger.Errorf("read next message failed for %s: %w", reader.Topic(), err)
+ }
+ if errors.Is(err, context.Canceled) {
+ return
+ }
+ tv.handleMessage(msg)
+ }
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/transaction.go b/vendor/github.com/apache/pulsar-client-go/pulsar/transaction.go
new file mode 100644
index 00000000..60e1d2bf
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/transaction.go
@@ -0,0 +1,69 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+)
+
+// TxnState The state of the transaction. Check the state of the transaction before executing some operation
+// with the transaction is necessary.
+type TxnState int32
+
+const (
+ _ TxnState = iota
+ // TxnOpen The transaction in TxnOpen state can be used to send/ack messages.
+ TxnOpen
+ // TxnCommitting The state of the transaction will be TxnCommitting after the commit method is called.
+ // The transaction in TxnCommitting state can be committed again.
+ TxnCommitting
+ // TxnAborting The state of the transaction will be TxnAborting after the abort method is called.
+ // The transaction in TxnAborting state can be aborted again.
+ TxnAborting
+ // TxnCommitted The state of the transaction will be TxnCommitted after the commit method is executed success.
+ // This means that all the operations with the transaction are success.
+ TxnCommitted
+ // TxnAborted The state of the transaction will be TxnAborted after the abort method is executed success.
+ // This means that all the operations with the transaction are aborted.
+ TxnAborted
+ // TxnError The state of the transaction will be TxnError after the operation of transaction get a non-retryable error.
+ TxnError
+ // TxnTimeout The state of the transaction will be TxnTimeout after the transaction timeout.
+ TxnTimeout
+)
+
+// TxnID An identifier for representing a transaction.
+type TxnID struct {
+ // mostSigBits The most significant 64 bits of this TxnID.
+ mostSigBits uint64
+ // leastSigBits The least significant 64 bits of this TxnID.
+ leastSigBits uint64
+}
+
+// Transaction used to guarantee exactly-once
+type Transaction interface {
+ //Commit You can commit the transaction after all the sending/acknowledging operations with the transaction success.
+ Commit(context.Context) error
+ //Abort You can abort the transaction when you want to abort all the sending/acknowledging operations
+ // with the transaction.
+ Abort(context.Context) error
+ //GetState Get the state of the transaction.
+ GetState() TxnState
+ //GetTxnID Get the identified ID of the transaction.
+ GetTxnID() TxnID
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/transaction_coordinator_client.go b/vendor/github.com/apache/pulsar-client-go/pulsar/transaction_coordinator_client.go
new file mode 100644
index 00000000..1535fad1
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/transaction_coordinator_client.go
@@ -0,0 +1,216 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "strconv"
+ "sync/atomic"
+ "time"
+
+ "github.com/apache/pulsar-client-go/pulsar/internal"
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+ "google.golang.org/protobuf/proto"
+)
+
+type transactionCoordinatorClient struct {
+ client *client
+ cons []internal.Connection
+ epoch uint64
+ semaphore internal.Semaphore
+ log log.Logger
+}
+
+// TransactionCoordinatorAssign is the transaction_impl coordinator topic which is used to look up the broker
+// where the TC located.
+const TransactionCoordinatorAssign = "persistent://pulsar/system/transaction_coordinator_assign"
+
+// newTransactionCoordinatorClientImpl init a transactionImpl coordinator client and
+// acquire connections with all transactionImpl coordinators.
+func newTransactionCoordinatorClientImpl(client *client) *transactionCoordinatorClient {
+ tc := &transactionCoordinatorClient{
+ client: client,
+ semaphore: internal.NewSemaphore(1000),
+ }
+ tc.log = client.log.SubLogger(log.Fields{})
+ return tc
+}
+
+func (tc *transactionCoordinatorClient) start() error {
+ r, err := tc.client.lookupService.GetPartitionedTopicMetadata(TransactionCoordinatorAssign)
+ if err != nil {
+ return err
+ }
+ tc.cons = make([]internal.Connection, r.Partitions)
+
+ //Get connections with all transaction_impl coordinators which is synchronized
+ for i := 0; i < r.Partitions; i++ {
+ err := tc.grabConn(uint64(i))
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (tc *transactionCoordinatorClient) grabConn(partition uint64) error {
+ lr, err := tc.client.lookupService.Lookup(getTCAssignTopicName(partition))
+ if err != nil {
+ tc.log.WithError(err).Warn("Failed to lookup the transaction_impl " +
+ "coordinator assign topic [" + strconv.FormatUint(partition, 10) + "]")
+ return err
+ }
+
+ requestID := tc.client.rpcClient.NewRequestID()
+ cmdTCConnect := pb.CommandTcClientConnectRequest{
+ RequestId: proto.Uint64(requestID),
+ TcId: proto.Uint64(partition),
+ }
+
+ res, err := tc.client.rpcClient.Request(lr.LogicalAddr, lr.PhysicalAddr, requestID,
+ pb.BaseCommand_TC_CLIENT_CONNECT_REQUEST, &cmdTCConnect)
+
+ if err != nil {
+ tc.log.WithError(err).Error("Failed to connect transaction_impl coordinator " +
+ strconv.FormatUint(partition, 10))
+ return err
+ }
+ tc.cons[partition] = res.Cnx
+ return nil
+}
+
+func (tc *transactionCoordinatorClient) close() {
+ for _, con := range tc.cons {
+ con.Close()
+ }
+}
+
+// newTransaction new a transactionImpl which can be used to guarantee exactly-once semantics.
+func (tc *transactionCoordinatorClient) newTransaction(timeout time.Duration) (*TxnID, error) {
+ if err := tc.canSendRequest(); err != nil {
+ return nil, err
+ }
+ requestID := tc.client.rpcClient.NewRequestID()
+ nextTcID := tc.nextTCNumber()
+ cmdNewTxn := &pb.CommandNewTxn{
+ RequestId: proto.Uint64(requestID),
+ TcId: proto.Uint64(nextTcID),
+ TxnTtlSeconds: proto.Uint64(uint64(timeout.Milliseconds())),
+ }
+
+ res, err := tc.client.rpcClient.RequestOnCnx(tc.cons[nextTcID], requestID, pb.BaseCommand_NEW_TXN, cmdNewTxn)
+ tc.semaphore.Release()
+ if err != nil {
+ return nil, err
+ } else if res.Response.NewTxnResponse.Error != nil {
+ return nil, getErrorFromServerError(res.Response.NewTxnResponse.Error)
+ }
+
+ return &TxnID{*res.Response.NewTxnResponse.TxnidMostBits,
+ *res.Response.NewTxnResponse.TxnidLeastBits}, nil
+}
+
+// addPublishPartitionToTxn register the partitions which published messages with the transactionImpl.
+// And this can be used when ending the transactionImpl.
+func (tc *transactionCoordinatorClient) addPublishPartitionToTxn(id *TxnID, partitions []string) error {
+ if err := tc.canSendRequest(); err != nil {
+ return err
+ }
+ requestID := tc.client.rpcClient.NewRequestID()
+ cmdAddPartitions := &pb.CommandAddPartitionToTxn{
+ RequestId: proto.Uint64(requestID),
+ TxnidMostBits: proto.Uint64(id.mostSigBits),
+ TxnidLeastBits: proto.Uint64(id.leastSigBits),
+ Partitions: partitions,
+ }
+ res, err := tc.client.rpcClient.RequestOnCnx(tc.cons[id.mostSigBits], requestID,
+ pb.BaseCommand_ADD_PARTITION_TO_TXN, cmdAddPartitions)
+ tc.semaphore.Release()
+ if err != nil {
+ return err
+ } else if res.Response.AddPartitionToTxnResponse.Error != nil {
+ return getErrorFromServerError(res.Response.AddPartitionToTxnResponse.Error)
+ }
+ return nil
+}
+
+// addSubscriptionToTxn register the subscription which acked messages with the transactionImpl.
+// And this can be used when ending the transactionImpl.
+func (tc *transactionCoordinatorClient) addSubscriptionToTxn(id *TxnID, topic string, subscription string) error {
+ if err := tc.canSendRequest(); err != nil {
+ return err
+ }
+ requestID := tc.client.rpcClient.NewRequestID()
+ sub := &pb.Subscription{
+ Topic: &topic,
+ Subscription: &subscription,
+ }
+ cmdAddSubscription := &pb.CommandAddSubscriptionToTxn{
+ RequestId: proto.Uint64(requestID),
+ TxnidMostBits: proto.Uint64(id.mostSigBits),
+ TxnidLeastBits: proto.Uint64(id.leastSigBits),
+ Subscription: []*pb.Subscription{sub},
+ }
+ res, err := tc.client.rpcClient.RequestOnCnx(tc.cons[id.mostSigBits], requestID,
+ pb.BaseCommand_ADD_SUBSCRIPTION_TO_TXN, cmdAddSubscription)
+ tc.semaphore.Release()
+ if err != nil {
+ return err
+ } else if res.Response.AddSubscriptionToTxnResponse.Error != nil {
+ return getErrorFromServerError(res.Response.AddSubscriptionToTxnResponse.Error)
+ }
+ return nil
+}
+
+// endTxn commit or abort the transactionImpl.
+func (tc *transactionCoordinatorClient) endTxn(id *TxnID, action pb.TxnAction) error {
+ if err := tc.canSendRequest(); err != nil {
+ return err
+ }
+ requestID := tc.client.rpcClient.NewRequestID()
+ cmdEndTxn := &pb.CommandEndTxn{
+ RequestId: proto.Uint64(requestID),
+ TxnAction: &action,
+ TxnidMostBits: proto.Uint64(id.mostSigBits),
+ TxnidLeastBits: proto.Uint64(id.leastSigBits),
+ }
+ res, err := tc.client.rpcClient.RequestOnCnx(tc.cons[id.mostSigBits], requestID, pb.BaseCommand_END_TXN, cmdEndTxn)
+ tc.semaphore.Release()
+ if err != nil {
+ return err
+ } else if res.Response.EndTxnResponse.Error != nil {
+ return getErrorFromServerError(res.Response.EndTxnResponse.Error)
+ }
+ return nil
+}
+
+func getTCAssignTopicName(partition uint64) string {
+ return TransactionCoordinatorAssign + "-partition-" + strconv.FormatUint(partition, 10)
+}
+
+func (tc *transactionCoordinatorClient) canSendRequest() error {
+ if !tc.semaphore.Acquire(context.Background()) {
+ return newError(UnknownError, "Failed to acquire semaphore")
+ }
+ return nil
+}
+
+func (tc *transactionCoordinatorClient) nextTCNumber() uint64 {
+ return atomic.AddUint64(&tc.epoch, 1) % uint64(len(tc.cons))
+}
diff --git a/vendor/github.com/apache/pulsar-client-go/pulsar/transaction_impl.go b/vendor/github.com/apache/pulsar-client-go/pulsar/transaction_impl.go
new file mode 100644
index 00000000..7cc93eca
--- /dev/null
+++ b/vendor/github.com/apache/pulsar-client-go/pulsar/transaction_impl.go
@@ -0,0 +1,237 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package pulsar
+
+import (
+ "context"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"
+ "github.com/apache/pulsar-client-go/pulsar/log"
+)
+
+type subscription struct {
+ topic string
+ subscription string
+}
+
+type transaction struct {
+ sync.Mutex
+ txnID TxnID
+ state TxnState
+ tcClient *transactionCoordinatorClient
+ registerPartitions map[string]bool
+ registerAckSubscriptions map[subscription]bool
+ // opsFlow It has two effects:
+ // 1. Wait all the operations of sending and acking messages with the transaction complete
+ // by reading msg from the chan.
+ // 2. Prevent sending or acking messages with a committed or aborted transaction.
+ // opsCount is record the number of the uncompleted operations.
+ // opsFlow
+ // Write:
+ // 1. When the transaction is created, a bool will be written to opsFlow chan.
+ // 2. When the opsCount decrement from 1 to 0, a new bool will be written to opsFlow chan.
+ // 3. When get a retryable error after committing or aborting the transaction,
+ // a bool will be written to opsFlow chan.
+ // Read:
+ // 1. When the transaction is committed or aborted, a bool will be read from opsFlow chan.
+ // 2. When the opsCount increment from 0 to 1, a bool will be read from opsFlow chan.
+ opsFlow chan bool
+ opsCount int32
+ opTimeout time.Duration
+ log log.Logger
+}
+
+func newTransaction(id TxnID, tcClient *transactionCoordinatorClient, timeout time.Duration) *transaction {
+ transaction := &transaction{
+ txnID: id,
+ state: TxnOpen,
+ registerPartitions: make(map[string]bool),
+ registerAckSubscriptions: make(map[subscription]bool),
+ opsFlow: make(chan bool, 1),
+ opTimeout: 5 * time.Second,
+ tcClient: tcClient,
+ }
+ //This means there are not pending requests with this transaction. The transaction can be committed or aborted.
+ transaction.opsFlow <- true
+ go func() {
+ //Set the state of the transaction to timeout after timeout
+ <-time.After(timeout)
+ atomic.CompareAndSwapInt32((*int32)(&transaction.state), int32(TxnOpen), int32(TxnTimeout))
+ }()
+ transaction.log = tcClient.log.SubLogger(log.Fields{})
+ return transaction
+}
+
+func (txn *transaction) GetState() TxnState {
+ return txn.state
+}
+
+func (txn *transaction) Commit(ctx context.Context) error {
+ if !(atomic.CompareAndSwapInt32((*int32)(&txn.state), int32(TxnOpen), int32(TxnCommitting)) ||
+ txn.state == TxnCommitting) {
+ return newError(InvalidStatus, "Expect transaction state is TxnOpen but "+txn.state.string())
+ }
+
+ //Wait for all operations to complete
+ select {
+ case <-txn.opsFlow:
+ case <-time.After(txn.opTimeout):
+ return newError(TimeoutError, "There are some operations that are not completed after the timeout.")
+ }
+ //Send commit transaction command to transaction coordinator
+ err := txn.tcClient.endTxn(&txn.txnID, pb.TxnAction_COMMIT)
+ if err == nil {
+ atomic.StoreInt32((*int32)(&txn.state), int32(TxnCommitted))
+ } else {
+ if err.(*Error).Result() == TransactionNoFoundError || err.(*Error).Result() == InvalidStatus {
+ atomic.StoreInt32((*int32)(&txn.state), int32(TxnError))
+ return err
+ }
+ txn.opsFlow <- true
+ }
+ return err
+}
+
+func (txn *transaction) Abort(ctx context.Context) error {
+ if !(atomic.CompareAndSwapInt32((*int32)(&txn.state), int32(TxnOpen), int32(TxnAborting)) ||
+ txn.state == TxnAborting) {
+ return newError(InvalidStatus, "Expect transaction state is TxnOpen but "+txn.state.string())
+ }
+
+ //Wait for all operations to complete
+ select {
+ case <-txn.opsFlow:
+ case <-time.After(txn.opTimeout):
+ return newError(TimeoutError, "There are some operations that are not completed after the timeout.")
+ }
+ //Send abort transaction command to transaction coordinator
+ err := txn.tcClient.endTxn(&txn.txnID, pb.TxnAction_ABORT)
+ if err == nil {
+ atomic.StoreInt32((*int32)(&txn.state), int32(TxnAborted))
+ } else {
+ if err.(*Error).Result() == TransactionNoFoundError || err.(*Error).Result() == InvalidStatus {
+ atomic.StoreInt32((*int32)(&txn.state), int32(TxnError))
+ } else {
+ txn.opsFlow <- true
+ }
+ }
+ return err
+}
+
+func (txn *transaction) registerSendOrAckOp() error {
+ if atomic.AddInt32(&txn.opsCount, 1) == 1 {
+ //There are new operations that not completed
+ select {
+ case <-txn.opsFlow:
+ return nil
+ case <-time.After(txn.opTimeout):
+ if _, err := txn.checkIfOpen(); err != nil {
+ return err
+ }
+ return newError(TimeoutError, "Failed to get the semaphore to register the send/ack operation")
+ }
+ }
+ return nil
+}
+
+func (txn *transaction) endSendOrAckOp(err error) {
+ if err != nil {
+ atomic.StoreInt32((*int32)(&txn.state), int32(TxnError))
+ }
+ if atomic.AddInt32(&txn.opsCount, -1) == 0 {
+ //This means there are not pending send/ack requests
+ txn.opsFlow <- true
+ }
+}
+
+func (txn *transaction) registerProducerTopic(topic string) error {
+ isOpen, err := txn.checkIfOpen()
+ if !isOpen {
+ return err
+ }
+ _, ok := txn.registerPartitions[topic]
+ if !ok {
+ txn.Lock()
+ defer txn.Unlock()
+ if _, ok = txn.registerPartitions[topic]; !ok {
+ err := txn.tcClient.addPublishPartitionToTxn(&txn.txnID, []string{topic})
+ if err != nil {
+ return err
+ }
+ txn.registerPartitions[topic] = true
+ }
+ }
+ return nil
+}
+
+func (txn *transaction) registerAckTopic(topic string, subName string) error {
+ isOpen, err := txn.checkIfOpen()
+ if !isOpen {
+ return err
+ }
+ sub := subscription{
+ topic: topic,
+ subscription: subName,
+ }
+ _, ok := txn.registerAckSubscriptions[sub]
+ if !ok {
+ txn.Lock()
+ defer txn.Unlock()
+ if _, ok = txn.registerAckSubscriptions[sub]; !ok {
+ err := txn.tcClient.addSubscriptionToTxn(&txn.txnID, topic, subName)
+ if err != nil {
+ return err
+ }
+ txn.registerAckSubscriptions[sub] = true
+ }
+ }
+ return nil
+}
+
+func (txn *transaction) GetTxnID() TxnID {
+ return txn.txnID
+}
+
+func (txn *transaction) checkIfOpen() (bool, error) {
+ if txn.state == TxnOpen {
+ return true, nil
+ }
+ return false, newError(InvalidStatus, "Expect transaction state is TxnOpen but "+txn.state.string())
+}
+
+func (state TxnState) string() string {
+ switch state {
+ case TxnOpen:
+ return "TxnOpen"
+ case TxnCommitting:
+ return "TxnCommitting"
+ case TxnAborting:
+ return "TxnAborting"
+ case TxnCommitted:
+ return "TxnCommitted"
+ case TxnAborted:
+ return "TxnAborted"
+ case TxnTimeout:
+ return "TxnTimeout"
+ default:
+ return "Unknown"
+ }
+}