From 40a3d2f5bd3ac57e075bc23b076c1e5df8436fc8 Mon Sep 17 00:00:00 2001 From: Sidhant Kohli Date: Fri, 30 Aug 2024 16:37:07 -0700 Subject: [PATCH] feat: allow configurable retryStrategy (#2010) Signed-off-by: Sidhant Kohli Signed-off-by: Vigith Maurice Co-authored-by: Vigith Maurice --- api/json-schema/schema.json | 33 + api/openapi-spec/swagger.json | 33 + .../numaflow.numaproj.io_monovertices.yaml | 15 + .../full/numaflow.numaproj.io_pipelines.yaml | 15 + .../full/numaflow.numaproj.io_vertices.yaml | 15 + config/install.yaml | 45 + config/namespace-install.yaml | 45 + docs/APIs.md | 218 +++ pkg/apis/numaflow/v1alpha1/const.go | 24 + pkg/apis/numaflow/v1alpha1/generated.pb.go | 1586 +++++++++++------ pkg/apis/numaflow/v1alpha1/generated.proto | 29 + .../numaflow/v1alpha1/openapi_generated.go | 67 +- pkg/apis/numaflow/v1alpha1/retry_strategy.go | 102 ++ .../numaflow/v1alpha1/retry_strategy_test.go | 115 ++ pkg/apis/numaflow/v1alpha1/sink.go | 3 + .../v1alpha1/zz_generated.deepcopy.go | 53 + pkg/metrics/metrics.go | 26 +- pkg/reconciler/pipeline/validate.go | 34 + pkg/reconciler/pipeline/validate_test.go | 122 ++ pkg/sinks/forward/forward.go | 238 ++- pkg/sinks/forward/options.go | 13 - rust/Cargo.lock | 1 + rust/monovertex/Cargo.toml | 1 + rust/monovertex/src/config.rs | 286 ++- rust/monovertex/src/forwarder.rs | 250 ++- rust/monovertex/src/metrics.rs | 24 +- rust/numaflow-models/src/models/backoff.rs | 38 + rust/numaflow-models/src/models/mod.rs | 4 + .../src/models/retry_strategy.rs | 38 + rust/numaflow-models/src/models/sink.rs | 3 + 30 files changed, 2752 insertions(+), 724 deletions(-) create mode 100644 pkg/apis/numaflow/v1alpha1/retry_strategy.go create mode 100644 pkg/apis/numaflow/v1alpha1/retry_strategy_test.go create mode 100644 rust/numaflow-models/src/models/backoff.rs create mode 100644 rust/numaflow-models/src/models/retry_strategy.rs diff --git a/api/json-schema/schema.json b/api/json-schema/schema.json index 584220c245..496b6a963f 100644 --- a/api/json-schema/schema.json +++ b/api/json-schema/schema.json @@ -17808,6 +17808,21 @@ }, "type": "object" }, + "io.numaproj.numaflow.v1alpha1.Backoff": { + "description": "Backoff defines parameters used to systematically configure the retry strategy.", + "properties": { + "interval": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Duration", + "description": "Interval sets the delay to wait before retry, after a failure occurs." + }, + "steps": { + "description": "Steps defines the number of times to try writing to a sink including retries", + "format": "int64", + "type": "integer" + } + }, + "type": "object" + }, "io.numaproj.numaflow.v1alpha1.BasicAuth": { "description": "BasicAuth represents the basic authentication approach which contains a user name and a password.", "properties": { @@ -19752,6 +19767,20 @@ }, "type": "object" }, + "io.numaproj.numaflow.v1alpha1.RetryStrategy": { + "description": "RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. It includes a BackOff strategy to manage the timing of retries and defines the action to take upon failure.", + "properties": { + "backoff": { + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.Backoff", + "description": "BackOff specifies the parameters for the backoff strategy, controlling how delays between retries should increase." + }, + "onFailure": { + "description": "OnFailure specifies the action to take when a retry fails. The default action is to retry.", + "type": "string" + } + }, + "type": "object" + }, "io.numaproj.numaflow.v1alpha1.SASL": { "properties": { "gssapi": { @@ -20064,6 +20093,10 @@ "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.Log", "description": "Log sink is used to write the data to the log." }, + "retryStrategy": { + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.RetryStrategy", + "description": "RetryStrategy struct encapsulates the settings for retrying operations in the event of failures." + }, "udsink": { "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.UDSink", "description": "UDSink sink is used to write the data to the user-defined sink." diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index a326712b6c..41d81a0efb 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -17812,6 +17812,21 @@ } } }, + "io.numaproj.numaflow.v1alpha1.Backoff": { + "description": "Backoff defines parameters used to systematically configure the retry strategy.", + "type": "object", + "properties": { + "interval": { + "description": "Interval sets the delay to wait before retry, after a failure occurs.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Duration" + }, + "steps": { + "description": "Steps defines the number of times to try writing to a sink including retries", + "type": "integer", + "format": "int64" + } + } + }, "io.numaproj.numaflow.v1alpha1.BasicAuth": { "description": "BasicAuth represents the basic authentication approach which contains a user name and a password.", "type": "object", @@ -19738,6 +19753,20 @@ } } }, + "io.numaproj.numaflow.v1alpha1.RetryStrategy": { + "description": "RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. It includes a BackOff strategy to manage the timing of retries and defines the action to take upon failure.", + "type": "object", + "properties": { + "backoff": { + "description": "BackOff specifies the parameters for the backoff strategy, controlling how delays between retries should increase.", + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.Backoff" + }, + "onFailure": { + "description": "OnFailure specifies the action to take when a retry fails. The default action is to retry.", + "type": "string" + } + } + }, "io.numaproj.numaflow.v1alpha1.SASL": { "type": "object", "required": [ @@ -20051,6 +20080,10 @@ "description": "Log sink is used to write the data to the log.", "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.Log" }, + "retryStrategy": { + "description": "RetryStrategy struct encapsulates the settings for retrying operations in the event of failures.", + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.RetryStrategy" + }, "udsink": { "description": "UDSink sink is used to write the data to the user-defined sink.", "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.UDSink" diff --git a/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml b/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml index d456bbb249..c07e927f5b 100644 --- a/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml +++ b/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml @@ -3615,6 +3615,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: diff --git a/config/base/crds/full/numaflow.numaproj.io_pipelines.yaml b/config/base/crds/full/numaflow.numaproj.io_pipelines.yaml index 070ba0b033..4ddc954f61 100644 --- a/config/base/crds/full/numaflow.numaproj.io_pipelines.yaml +++ b/config/base/crds/full/numaflow.numaproj.io_pipelines.yaml @@ -7571,6 +7571,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: diff --git a/config/base/crds/full/numaflow.numaproj.io_vertices.yaml b/config/base/crds/full/numaflow.numaproj.io_vertices.yaml index 7973694b88..8f0d150360 100644 --- a/config/base/crds/full/numaflow.numaproj.io_vertices.yaml +++ b/config/base/crds/full/numaflow.numaproj.io_vertices.yaml @@ -3158,6 +3158,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: diff --git a/config/install.yaml b/config/install.yaml index a648c1413e..d2e76c26b3 100644 --- a/config/install.yaml +++ b/config/install.yaml @@ -6259,6 +6259,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: @@ -15799,6 +15814,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: @@ -21243,6 +21273,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: diff --git a/config/namespace-install.yaml b/config/namespace-install.yaml index a922d0f7c5..13afdb3228 100644 --- a/config/namespace-install.yaml +++ b/config/namespace-install.yaml @@ -6259,6 +6259,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: @@ -15799,6 +15814,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: @@ -21243,6 +21273,21 @@ spec: type: object log: type: object + retryStrategy: + properties: + backoff: + properties: + interval: + default: 1ms + type: string + steps: + format: int32 + type: integer + type: object + onFailure: + default: retry + type: string + type: object udsink: properties: container: diff --git a/docs/APIs.md b/docs/APIs.md index b5ba81450d..3e631f3870 100644 --- a/docs/APIs.md +++ b/docs/APIs.md @@ -908,6 +908,94 @@ needs to add “Authorization: Bearer ” in the header +

+ +Backoff +

+ +

+ +(Appears on: +RetryStrategy) +

+ +

+ +

+ +Backoff defines parameters used to systematically configure the retry +strategy. +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +Field + + +Description +
+ +interval
+ +Kubernetes meta/v1.Duration +
+ +(Optional) +

+ +Interval sets the delay to wait before retry, after a failure occurs. +

+ +
+ +steps
uint32 +
+ +(Optional) +

+ +Steps defines the number of times to try writing to a sink including +retries +

+ +
+

BasicAuth @@ -6773,6 +6861,23 @@ etc.).

+

+ +OnFailureRetryStrategy (string alias) +

+ +

+ +

+ +(Appears on: +RetryStrategy) +

+ +

+ +

+

PBQStorage @@ -8126,6 +8231,97 @@ config +

+ +RetryStrategy +

+ +

+ +(Appears on: +Sink) +

+ +

+ +

+ +RetryStrategy struct encapsulates the settings for retrying operations +in the event of failures. It includes a BackOff strategy to manage the +timing of retries and defines the action to take upon failure. +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +Field + + +Description +
+ +backoff
+ Backoff +
+ +(Optional) +

+ +BackOff specifies the parameters for the backoff strategy, controlling +how delays between retries should increase. +

+ +
+ +onFailure
+ +OnFailureRetryStrategy +
+ +(Optional) +

+ +OnFailure specifies the action to take when a retry fails. The default +action is to retry. +

+ +
+

SASL @@ -9318,6 +9514,28 @@ it. + + + + +retryStrategy
+ RetryStrategy + + + + + +(Optional) +

+ +RetryStrategy struct encapsulates the settings for retrying operations +in the event of failures. +

+ + + + + diff --git a/pkg/apis/numaflow/v1alpha1/const.go b/pkg/apis/numaflow/v1alpha1/const.go index 8677101378..d0e9eb62f0 100644 --- a/pkg/apis/numaflow/v1alpha1/const.go +++ b/pkg/apis/numaflow/v1alpha1/const.go @@ -18,6 +18,7 @@ package v1alpha1 import ( "fmt" + "math" "time" ) @@ -243,6 +244,29 @@ const ( // Serving source DefaultServingTTL = 24 * time.Hour + + // Retry Strategy + + // DefaultRetryInterval specifies the default time interval between retry attempts. + // This value can be adjusted depending on the specific requirements + // for responsiveness and system load considerations. + DefaultRetryInterval = 1 * time.Millisecond + + // DefaultRetrySteps is defined to dictate how many times the platform should attempt to retry + // a write operation to a sink following a failure. The value is set to math.MaxInt32 - 1, + // effectively indicating an almost indefinite number of retries. This large default is chosen + // to ensure that the system will try persistently to carry out the operation unless explicitly + // configured otherwise. This approach can be useful in environments where loss of data + // due to intermittent failures is unacceptable. + DefaultRetrySteps = math.MaxInt32 - 1 + + // DefaultOnFailureRetryStrategy specifies the strategy to be used when the write to a sink fails and + // the retries count specified are exhausted. + // Setting this to 'OnFailureRetry' means the system is configured by default + // to retry the failed operation until successful completion. + // This strategy argues for robustness in operations, aiming + // to minimize the chances of data loss or failed deliveries in transient failure scenarios. + DefaultOnFailureRetryStrategy = OnFailureRetry ) var ( diff --git a/pkg/apis/numaflow/v1alpha1/generated.pb.go b/pkg/apis/numaflow/v1alpha1/generated.pb.go index 3a29fb484b..3514c89361 100644 --- a/pkg/apis/numaflow/v1alpha1/generated.pb.go +++ b/pkg/apis/numaflow/v1alpha1/generated.pb.go @@ -160,10 +160,38 @@ func (m *Authorization) XXX_DiscardUnknown() { var xxx_messageInfo_Authorization proto.InternalMessageInfo +func (m *Backoff) Reset() { *m = Backoff{} } +func (*Backoff) ProtoMessage() {} +func (*Backoff) Descriptor() ([]byte, []int) { + return fileDescriptor_9d0d1b17d3865563, []int{4} +} +func (m *Backoff) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Backoff) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *Backoff) XXX_Merge(src proto.Message) { + xxx_messageInfo_Backoff.Merge(m, src) +} +func (m *Backoff) XXX_Size() int { + return m.Size() +} +func (m *Backoff) XXX_DiscardUnknown() { + xxx_messageInfo_Backoff.DiscardUnknown(m) +} + +var xxx_messageInfo_Backoff proto.InternalMessageInfo + func (m *BasicAuth) Reset() { *m = BasicAuth{} } func (*BasicAuth) ProtoMessage() {} func (*BasicAuth) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{4} + return fileDescriptor_9d0d1b17d3865563, []int{5} } func (m *BasicAuth) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -191,7 +219,7 @@ var xxx_messageInfo_BasicAuth proto.InternalMessageInfo func (m *Blackhole) Reset() { *m = Blackhole{} } func (*Blackhole) ProtoMessage() {} func (*Blackhole) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{5} + return fileDescriptor_9d0d1b17d3865563, []int{6} } func (m *Blackhole) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -219,7 +247,7 @@ var xxx_messageInfo_Blackhole proto.InternalMessageInfo func (m *BufferServiceConfig) Reset() { *m = BufferServiceConfig{} } func (*BufferServiceConfig) ProtoMessage() {} func (*BufferServiceConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{6} + return fileDescriptor_9d0d1b17d3865563, []int{7} } func (m *BufferServiceConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -247,7 +275,7 @@ var xxx_messageInfo_BufferServiceConfig proto.InternalMessageInfo func (m *CombinedEdge) Reset() { *m = CombinedEdge{} } func (*CombinedEdge) ProtoMessage() {} func (*CombinedEdge) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{7} + return fileDescriptor_9d0d1b17d3865563, []int{8} } func (m *CombinedEdge) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -275,7 +303,7 @@ var xxx_messageInfo_CombinedEdge proto.InternalMessageInfo func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} func (*Container) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{8} + return fileDescriptor_9d0d1b17d3865563, []int{9} } func (m *Container) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -303,7 +331,7 @@ var xxx_messageInfo_Container proto.InternalMessageInfo func (m *ContainerTemplate) Reset() { *m = ContainerTemplate{} } func (*ContainerTemplate) ProtoMessage() {} func (*ContainerTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{9} + return fileDescriptor_9d0d1b17d3865563, []int{10} } func (m *ContainerTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -331,7 +359,7 @@ var xxx_messageInfo_ContainerTemplate proto.InternalMessageInfo func (m *DaemonTemplate) Reset() { *m = DaemonTemplate{} } func (*DaemonTemplate) ProtoMessage() {} func (*DaemonTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{10} + return fileDescriptor_9d0d1b17d3865563, []int{11} } func (m *DaemonTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -359,7 +387,7 @@ var xxx_messageInfo_DaemonTemplate proto.InternalMessageInfo func (m *Edge) Reset() { *m = Edge{} } func (*Edge) ProtoMessage() {} func (*Edge) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{11} + return fileDescriptor_9d0d1b17d3865563, []int{12} } func (m *Edge) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -387,7 +415,7 @@ var xxx_messageInfo_Edge proto.InternalMessageInfo func (m *FixedWindow) Reset() { *m = FixedWindow{} } func (*FixedWindow) ProtoMessage() {} func (*FixedWindow) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{12} + return fileDescriptor_9d0d1b17d3865563, []int{13} } func (m *FixedWindow) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -415,7 +443,7 @@ var xxx_messageInfo_FixedWindow proto.InternalMessageInfo func (m *ForwardConditions) Reset() { *m = ForwardConditions{} } func (*ForwardConditions) ProtoMessage() {} func (*ForwardConditions) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{13} + return fileDescriptor_9d0d1b17d3865563, []int{14} } func (m *ForwardConditions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -443,7 +471,7 @@ var xxx_messageInfo_ForwardConditions proto.InternalMessageInfo func (m *Function) Reset() { *m = Function{} } func (*Function) ProtoMessage() {} func (*Function) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{14} + return fileDescriptor_9d0d1b17d3865563, []int{15} } func (m *Function) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -471,7 +499,7 @@ var xxx_messageInfo_Function proto.InternalMessageInfo func (m *GSSAPI) Reset() { *m = GSSAPI{} } func (*GSSAPI) ProtoMessage() {} func (*GSSAPI) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{15} + return fileDescriptor_9d0d1b17d3865563, []int{16} } func (m *GSSAPI) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -499,7 +527,7 @@ var xxx_messageInfo_GSSAPI proto.InternalMessageInfo func (m *GeneratorSource) Reset() { *m = GeneratorSource{} } func (*GeneratorSource) ProtoMessage() {} func (*GeneratorSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{16} + return fileDescriptor_9d0d1b17d3865563, []int{17} } func (m *GeneratorSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -527,7 +555,7 @@ var xxx_messageInfo_GeneratorSource proto.InternalMessageInfo func (m *GetDaemonDeploymentReq) Reset() { *m = GetDaemonDeploymentReq{} } func (*GetDaemonDeploymentReq) ProtoMessage() {} func (*GetDaemonDeploymentReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{17} + return fileDescriptor_9d0d1b17d3865563, []int{18} } func (m *GetDaemonDeploymentReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -555,7 +583,7 @@ var xxx_messageInfo_GetDaemonDeploymentReq proto.InternalMessageInfo func (m *GetJetStreamServiceSpecReq) Reset() { *m = GetJetStreamServiceSpecReq{} } func (*GetJetStreamServiceSpecReq) ProtoMessage() {} func (*GetJetStreamServiceSpecReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{18} + return fileDescriptor_9d0d1b17d3865563, []int{19} } func (m *GetJetStreamServiceSpecReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -583,7 +611,7 @@ var xxx_messageInfo_GetJetStreamServiceSpecReq proto.InternalMessageInfo func (m *GetJetStreamStatefulSetSpecReq) Reset() { *m = GetJetStreamStatefulSetSpecReq{} } func (*GetJetStreamStatefulSetSpecReq) ProtoMessage() {} func (*GetJetStreamStatefulSetSpecReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{19} + return fileDescriptor_9d0d1b17d3865563, []int{20} } func (m *GetJetStreamStatefulSetSpecReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -611,7 +639,7 @@ var xxx_messageInfo_GetJetStreamStatefulSetSpecReq proto.InternalMessageInfo func (m *GetMonoVertexDaemonDeploymentReq) Reset() { *m = GetMonoVertexDaemonDeploymentReq{} } func (*GetMonoVertexDaemonDeploymentReq) ProtoMessage() {} func (*GetMonoVertexDaemonDeploymentReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{20} + return fileDescriptor_9d0d1b17d3865563, []int{21} } func (m *GetMonoVertexDaemonDeploymentReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -639,7 +667,7 @@ var xxx_messageInfo_GetMonoVertexDaemonDeploymentReq proto.InternalMessageInfo func (m *GetMonoVertexPodSpecReq) Reset() { *m = GetMonoVertexPodSpecReq{} } func (*GetMonoVertexPodSpecReq) ProtoMessage() {} func (*GetMonoVertexPodSpecReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{21} + return fileDescriptor_9d0d1b17d3865563, []int{22} } func (m *GetMonoVertexPodSpecReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -667,7 +695,7 @@ var xxx_messageInfo_GetMonoVertexPodSpecReq proto.InternalMessageInfo func (m *GetRedisServiceSpecReq) Reset() { *m = GetRedisServiceSpecReq{} } func (*GetRedisServiceSpecReq) ProtoMessage() {} func (*GetRedisServiceSpecReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{22} + return fileDescriptor_9d0d1b17d3865563, []int{23} } func (m *GetRedisServiceSpecReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -695,7 +723,7 @@ var xxx_messageInfo_GetRedisServiceSpecReq proto.InternalMessageInfo func (m *GetRedisStatefulSetSpecReq) Reset() { *m = GetRedisStatefulSetSpecReq{} } func (*GetRedisStatefulSetSpecReq) ProtoMessage() {} func (*GetRedisStatefulSetSpecReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{23} + return fileDescriptor_9d0d1b17d3865563, []int{24} } func (m *GetRedisStatefulSetSpecReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -723,7 +751,7 @@ var xxx_messageInfo_GetRedisStatefulSetSpecReq proto.InternalMessageInfo func (m *GetSideInputDeploymentReq) Reset() { *m = GetSideInputDeploymentReq{} } func (*GetSideInputDeploymentReq) ProtoMessage() {} func (*GetSideInputDeploymentReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{24} + return fileDescriptor_9d0d1b17d3865563, []int{25} } func (m *GetSideInputDeploymentReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -751,7 +779,7 @@ var xxx_messageInfo_GetSideInputDeploymentReq proto.InternalMessageInfo func (m *GetVertexPodSpecReq) Reset() { *m = GetVertexPodSpecReq{} } func (*GetVertexPodSpecReq) ProtoMessage() {} func (*GetVertexPodSpecReq) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{25} + return fileDescriptor_9d0d1b17d3865563, []int{26} } func (m *GetVertexPodSpecReq) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -779,7 +807,7 @@ var xxx_messageInfo_GetVertexPodSpecReq proto.InternalMessageInfo func (m *GroupBy) Reset() { *m = GroupBy{} } func (*GroupBy) ProtoMessage() {} func (*GroupBy) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{26} + return fileDescriptor_9d0d1b17d3865563, []int{27} } func (m *GroupBy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -807,7 +835,7 @@ var xxx_messageInfo_GroupBy proto.InternalMessageInfo func (m *HTTPSource) Reset() { *m = HTTPSource{} } func (*HTTPSource) ProtoMessage() {} func (*HTTPSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{27} + return fileDescriptor_9d0d1b17d3865563, []int{28} } func (m *HTTPSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -835,7 +863,7 @@ var xxx_messageInfo_HTTPSource proto.InternalMessageInfo func (m *IdleSource) Reset() { *m = IdleSource{} } func (*IdleSource) ProtoMessage() {} func (*IdleSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{28} + return fileDescriptor_9d0d1b17d3865563, []int{29} } func (m *IdleSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -863,7 +891,7 @@ var xxx_messageInfo_IdleSource proto.InternalMessageInfo func (m *InterStepBufferService) Reset() { *m = InterStepBufferService{} } func (*InterStepBufferService) ProtoMessage() {} func (*InterStepBufferService) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{29} + return fileDescriptor_9d0d1b17d3865563, []int{30} } func (m *InterStepBufferService) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -891,7 +919,7 @@ var xxx_messageInfo_InterStepBufferService proto.InternalMessageInfo func (m *InterStepBufferServiceList) Reset() { *m = InterStepBufferServiceList{} } func (*InterStepBufferServiceList) ProtoMessage() {} func (*InterStepBufferServiceList) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{30} + return fileDescriptor_9d0d1b17d3865563, []int{31} } func (m *InterStepBufferServiceList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -919,7 +947,7 @@ var xxx_messageInfo_InterStepBufferServiceList proto.InternalMessageInfo func (m *InterStepBufferServiceSpec) Reset() { *m = InterStepBufferServiceSpec{} } func (*InterStepBufferServiceSpec) ProtoMessage() {} func (*InterStepBufferServiceSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{31} + return fileDescriptor_9d0d1b17d3865563, []int{32} } func (m *InterStepBufferServiceSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -947,7 +975,7 @@ var xxx_messageInfo_InterStepBufferServiceSpec proto.InternalMessageInfo func (m *InterStepBufferServiceStatus) Reset() { *m = InterStepBufferServiceStatus{} } func (*InterStepBufferServiceStatus) ProtoMessage() {} func (*InterStepBufferServiceStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{32} + return fileDescriptor_9d0d1b17d3865563, []int{33} } func (m *InterStepBufferServiceStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -975,7 +1003,7 @@ var xxx_messageInfo_InterStepBufferServiceStatus proto.InternalMessageInfo func (m *JetStreamBufferService) Reset() { *m = JetStreamBufferService{} } func (*JetStreamBufferService) ProtoMessage() {} func (*JetStreamBufferService) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{33} + return fileDescriptor_9d0d1b17d3865563, []int{34} } func (m *JetStreamBufferService) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1003,7 +1031,7 @@ var xxx_messageInfo_JetStreamBufferService proto.InternalMessageInfo func (m *JetStreamConfig) Reset() { *m = JetStreamConfig{} } func (*JetStreamConfig) ProtoMessage() {} func (*JetStreamConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{34} + return fileDescriptor_9d0d1b17d3865563, []int{35} } func (m *JetStreamConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1031,7 +1059,7 @@ var xxx_messageInfo_JetStreamConfig proto.InternalMessageInfo func (m *JetStreamSource) Reset() { *m = JetStreamSource{} } func (*JetStreamSource) ProtoMessage() {} func (*JetStreamSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{35} + return fileDescriptor_9d0d1b17d3865563, []int{36} } func (m *JetStreamSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1059,7 +1087,7 @@ var xxx_messageInfo_JetStreamSource proto.InternalMessageInfo func (m *JobTemplate) Reset() { *m = JobTemplate{} } func (*JobTemplate) ProtoMessage() {} func (*JobTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{36} + return fileDescriptor_9d0d1b17d3865563, []int{37} } func (m *JobTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1087,7 +1115,7 @@ var xxx_messageInfo_JobTemplate proto.InternalMessageInfo func (m *KafkaSink) Reset() { *m = KafkaSink{} } func (*KafkaSink) ProtoMessage() {} func (*KafkaSink) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{37} + return fileDescriptor_9d0d1b17d3865563, []int{38} } func (m *KafkaSink) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1115,7 +1143,7 @@ var xxx_messageInfo_KafkaSink proto.InternalMessageInfo func (m *KafkaSource) Reset() { *m = KafkaSource{} } func (*KafkaSource) ProtoMessage() {} func (*KafkaSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{38} + return fileDescriptor_9d0d1b17d3865563, []int{39} } func (m *KafkaSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1143,7 +1171,7 @@ var xxx_messageInfo_KafkaSource proto.InternalMessageInfo func (m *Lifecycle) Reset() { *m = Lifecycle{} } func (*Lifecycle) ProtoMessage() {} func (*Lifecycle) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{39} + return fileDescriptor_9d0d1b17d3865563, []int{40} } func (m *Lifecycle) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1171,7 +1199,7 @@ var xxx_messageInfo_Lifecycle proto.InternalMessageInfo func (m *Log) Reset() { *m = Log{} } func (*Log) ProtoMessage() {} func (*Log) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{40} + return fileDescriptor_9d0d1b17d3865563, []int{41} } func (m *Log) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1199,7 +1227,7 @@ var xxx_messageInfo_Log proto.InternalMessageInfo func (m *Metadata) Reset() { *m = Metadata{} } func (*Metadata) ProtoMessage() {} func (*Metadata) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{41} + return fileDescriptor_9d0d1b17d3865563, []int{42} } func (m *Metadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1227,7 +1255,7 @@ var xxx_messageInfo_Metadata proto.InternalMessageInfo func (m *MonoVertex) Reset() { *m = MonoVertex{} } func (*MonoVertex) ProtoMessage() {} func (*MonoVertex) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{42} + return fileDescriptor_9d0d1b17d3865563, []int{43} } func (m *MonoVertex) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1255,7 +1283,7 @@ var xxx_messageInfo_MonoVertex proto.InternalMessageInfo func (m *MonoVertexLimits) Reset() { *m = MonoVertexLimits{} } func (*MonoVertexLimits) ProtoMessage() {} func (*MonoVertexLimits) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{43} + return fileDescriptor_9d0d1b17d3865563, []int{44} } func (m *MonoVertexLimits) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1283,7 +1311,7 @@ var xxx_messageInfo_MonoVertexLimits proto.InternalMessageInfo func (m *MonoVertexList) Reset() { *m = MonoVertexList{} } func (*MonoVertexList) ProtoMessage() {} func (*MonoVertexList) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{44} + return fileDescriptor_9d0d1b17d3865563, []int{45} } func (m *MonoVertexList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1311,7 +1339,7 @@ var xxx_messageInfo_MonoVertexList proto.InternalMessageInfo func (m *MonoVertexSpec) Reset() { *m = MonoVertexSpec{} } func (*MonoVertexSpec) ProtoMessage() {} func (*MonoVertexSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{45} + return fileDescriptor_9d0d1b17d3865563, []int{46} } func (m *MonoVertexSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1339,7 +1367,7 @@ var xxx_messageInfo_MonoVertexSpec proto.InternalMessageInfo func (m *MonoVertexStatus) Reset() { *m = MonoVertexStatus{} } func (*MonoVertexStatus) ProtoMessage() {} func (*MonoVertexStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{46} + return fileDescriptor_9d0d1b17d3865563, []int{47} } func (m *MonoVertexStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1367,7 +1395,7 @@ var xxx_messageInfo_MonoVertexStatus proto.InternalMessageInfo func (m *NativeRedis) Reset() { *m = NativeRedis{} } func (*NativeRedis) ProtoMessage() {} func (*NativeRedis) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{47} + return fileDescriptor_9d0d1b17d3865563, []int{48} } func (m *NativeRedis) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1395,7 +1423,7 @@ var xxx_messageInfo_NativeRedis proto.InternalMessageInfo func (m *NatsAuth) Reset() { *m = NatsAuth{} } func (*NatsAuth) ProtoMessage() {} func (*NatsAuth) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{48} + return fileDescriptor_9d0d1b17d3865563, []int{49} } func (m *NatsAuth) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1423,7 +1451,7 @@ var xxx_messageInfo_NatsAuth proto.InternalMessageInfo func (m *NatsSource) Reset() { *m = NatsSource{} } func (*NatsSource) ProtoMessage() {} func (*NatsSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{49} + return fileDescriptor_9d0d1b17d3865563, []int{50} } func (m *NatsSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1451,7 +1479,7 @@ var xxx_messageInfo_NatsSource proto.InternalMessageInfo func (m *NoStore) Reset() { *m = NoStore{} } func (*NoStore) ProtoMessage() {} func (*NoStore) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{50} + return fileDescriptor_9d0d1b17d3865563, []int{51} } func (m *NoStore) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1479,7 +1507,7 @@ var xxx_messageInfo_NoStore proto.InternalMessageInfo func (m *PBQStorage) Reset() { *m = PBQStorage{} } func (*PBQStorage) ProtoMessage() {} func (*PBQStorage) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{51} + return fileDescriptor_9d0d1b17d3865563, []int{52} } func (m *PBQStorage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1507,7 +1535,7 @@ var xxx_messageInfo_PBQStorage proto.InternalMessageInfo func (m *PersistenceStrategy) Reset() { *m = PersistenceStrategy{} } func (*PersistenceStrategy) ProtoMessage() {} func (*PersistenceStrategy) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{52} + return fileDescriptor_9d0d1b17d3865563, []int{53} } func (m *PersistenceStrategy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1535,7 +1563,7 @@ var xxx_messageInfo_PersistenceStrategy proto.InternalMessageInfo func (m *Pipeline) Reset() { *m = Pipeline{} } func (*Pipeline) ProtoMessage() {} func (*Pipeline) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{53} + return fileDescriptor_9d0d1b17d3865563, []int{54} } func (m *Pipeline) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1563,7 +1591,7 @@ var xxx_messageInfo_Pipeline proto.InternalMessageInfo func (m *PipelineLimits) Reset() { *m = PipelineLimits{} } func (*PipelineLimits) ProtoMessage() {} func (*PipelineLimits) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{54} + return fileDescriptor_9d0d1b17d3865563, []int{55} } func (m *PipelineLimits) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1591,7 +1619,7 @@ var xxx_messageInfo_PipelineLimits proto.InternalMessageInfo func (m *PipelineList) Reset() { *m = PipelineList{} } func (*PipelineList) ProtoMessage() {} func (*PipelineList) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{55} + return fileDescriptor_9d0d1b17d3865563, []int{56} } func (m *PipelineList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1619,7 +1647,7 @@ var xxx_messageInfo_PipelineList proto.InternalMessageInfo func (m *PipelineSpec) Reset() { *m = PipelineSpec{} } func (*PipelineSpec) ProtoMessage() {} func (*PipelineSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{56} + return fileDescriptor_9d0d1b17d3865563, []int{57} } func (m *PipelineSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1647,7 +1675,7 @@ var xxx_messageInfo_PipelineSpec proto.InternalMessageInfo func (m *PipelineStatus) Reset() { *m = PipelineStatus{} } func (*PipelineStatus) ProtoMessage() {} func (*PipelineStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{57} + return fileDescriptor_9d0d1b17d3865563, []int{58} } func (m *PipelineStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1675,7 +1703,7 @@ var xxx_messageInfo_PipelineStatus proto.InternalMessageInfo func (m *RedisBufferService) Reset() { *m = RedisBufferService{} } func (*RedisBufferService) ProtoMessage() {} func (*RedisBufferService) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{58} + return fileDescriptor_9d0d1b17d3865563, []int{59} } func (m *RedisBufferService) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1703,7 +1731,7 @@ var xxx_messageInfo_RedisBufferService proto.InternalMessageInfo func (m *RedisConfig) Reset() { *m = RedisConfig{} } func (*RedisConfig) ProtoMessage() {} func (*RedisConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{59} + return fileDescriptor_9d0d1b17d3865563, []int{60} } func (m *RedisConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1731,7 +1759,7 @@ var xxx_messageInfo_RedisConfig proto.InternalMessageInfo func (m *RedisSettings) Reset() { *m = RedisSettings{} } func (*RedisSettings) ProtoMessage() {} func (*RedisSettings) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{60} + return fileDescriptor_9d0d1b17d3865563, []int{61} } func (m *RedisSettings) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1756,10 +1784,38 @@ func (m *RedisSettings) XXX_DiscardUnknown() { var xxx_messageInfo_RedisSettings proto.InternalMessageInfo +func (m *RetryStrategy) Reset() { *m = RetryStrategy{} } +func (*RetryStrategy) ProtoMessage() {} +func (*RetryStrategy) Descriptor() ([]byte, []int) { + return fileDescriptor_9d0d1b17d3865563, []int{62} +} +func (m *RetryStrategy) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RetryStrategy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *RetryStrategy) XXX_Merge(src proto.Message) { + xxx_messageInfo_RetryStrategy.Merge(m, src) +} +func (m *RetryStrategy) XXX_Size() int { + return m.Size() +} +func (m *RetryStrategy) XXX_DiscardUnknown() { + xxx_messageInfo_RetryStrategy.DiscardUnknown(m) +} + +var xxx_messageInfo_RetryStrategy proto.InternalMessageInfo + func (m *SASL) Reset() { *m = SASL{} } func (*SASL) ProtoMessage() {} func (*SASL) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{61} + return fileDescriptor_9d0d1b17d3865563, []int{63} } func (m *SASL) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1787,7 +1843,7 @@ var xxx_messageInfo_SASL proto.InternalMessageInfo func (m *SASLPlain) Reset() { *m = SASLPlain{} } func (*SASLPlain) ProtoMessage() {} func (*SASLPlain) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{62} + return fileDescriptor_9d0d1b17d3865563, []int{64} } func (m *SASLPlain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1815,7 +1871,7 @@ var xxx_messageInfo_SASLPlain proto.InternalMessageInfo func (m *Scale) Reset() { *m = Scale{} } func (*Scale) ProtoMessage() {} func (*Scale) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{63} + return fileDescriptor_9d0d1b17d3865563, []int{65} } func (m *Scale) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1843,7 +1899,7 @@ var xxx_messageInfo_Scale proto.InternalMessageInfo func (m *ServingSource) Reset() { *m = ServingSource{} } func (*ServingSource) ProtoMessage() {} func (*ServingSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{64} + return fileDescriptor_9d0d1b17d3865563, []int{66} } func (m *ServingSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1871,7 +1927,7 @@ var xxx_messageInfo_ServingSource proto.InternalMessageInfo func (m *ServingStore) Reset() { *m = ServingStore{} } func (*ServingStore) ProtoMessage() {} func (*ServingStore) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{65} + return fileDescriptor_9d0d1b17d3865563, []int{67} } func (m *ServingStore) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1899,7 +1955,7 @@ var xxx_messageInfo_ServingStore proto.InternalMessageInfo func (m *SessionWindow) Reset() { *m = SessionWindow{} } func (*SessionWindow) ProtoMessage() {} func (*SessionWindow) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{66} + return fileDescriptor_9d0d1b17d3865563, []int{68} } func (m *SessionWindow) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1927,7 +1983,7 @@ var xxx_messageInfo_SessionWindow proto.InternalMessageInfo func (m *SideInput) Reset() { *m = SideInput{} } func (*SideInput) ProtoMessage() {} func (*SideInput) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{67} + return fileDescriptor_9d0d1b17d3865563, []int{69} } func (m *SideInput) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1955,7 +2011,7 @@ var xxx_messageInfo_SideInput proto.InternalMessageInfo func (m *SideInputTrigger) Reset() { *m = SideInputTrigger{} } func (*SideInputTrigger) ProtoMessage() {} func (*SideInputTrigger) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{68} + return fileDescriptor_9d0d1b17d3865563, []int{70} } func (m *SideInputTrigger) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1983,7 +2039,7 @@ var xxx_messageInfo_SideInputTrigger proto.InternalMessageInfo func (m *SideInputsManagerTemplate) Reset() { *m = SideInputsManagerTemplate{} } func (*SideInputsManagerTemplate) ProtoMessage() {} func (*SideInputsManagerTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{69} + return fileDescriptor_9d0d1b17d3865563, []int{71} } func (m *SideInputsManagerTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2011,7 +2067,7 @@ var xxx_messageInfo_SideInputsManagerTemplate proto.InternalMessageInfo func (m *Sink) Reset() { *m = Sink{} } func (*Sink) ProtoMessage() {} func (*Sink) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{70} + return fileDescriptor_9d0d1b17d3865563, []int{72} } func (m *Sink) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2039,7 +2095,7 @@ var xxx_messageInfo_Sink proto.InternalMessageInfo func (m *SlidingWindow) Reset() { *m = SlidingWindow{} } func (*SlidingWindow) ProtoMessage() {} func (*SlidingWindow) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{71} + return fileDescriptor_9d0d1b17d3865563, []int{73} } func (m *SlidingWindow) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2067,7 +2123,7 @@ var xxx_messageInfo_SlidingWindow proto.InternalMessageInfo func (m *Source) Reset() { *m = Source{} } func (*Source) ProtoMessage() {} func (*Source) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{72} + return fileDescriptor_9d0d1b17d3865563, []int{74} } func (m *Source) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2095,7 +2151,7 @@ var xxx_messageInfo_Source proto.InternalMessageInfo func (m *Status) Reset() { *m = Status{} } func (*Status) ProtoMessage() {} func (*Status) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{73} + return fileDescriptor_9d0d1b17d3865563, []int{75} } func (m *Status) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2123,7 +2179,7 @@ var xxx_messageInfo_Status proto.InternalMessageInfo func (m *TLS) Reset() { *m = TLS{} } func (*TLS) ProtoMessage() {} func (*TLS) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{74} + return fileDescriptor_9d0d1b17d3865563, []int{76} } func (m *TLS) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2151,7 +2207,7 @@ var xxx_messageInfo_TLS proto.InternalMessageInfo func (m *TagConditions) Reset() { *m = TagConditions{} } func (*TagConditions) ProtoMessage() {} func (*TagConditions) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{75} + return fileDescriptor_9d0d1b17d3865563, []int{77} } func (m *TagConditions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2179,7 +2235,7 @@ var xxx_messageInfo_TagConditions proto.InternalMessageInfo func (m *Templates) Reset() { *m = Templates{} } func (*Templates) ProtoMessage() {} func (*Templates) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{76} + return fileDescriptor_9d0d1b17d3865563, []int{78} } func (m *Templates) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2207,7 +2263,7 @@ var xxx_messageInfo_Templates proto.InternalMessageInfo func (m *Transformer) Reset() { *m = Transformer{} } func (*Transformer) ProtoMessage() {} func (*Transformer) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{77} + return fileDescriptor_9d0d1b17d3865563, []int{79} } func (m *Transformer) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2235,7 +2291,7 @@ var xxx_messageInfo_Transformer proto.InternalMessageInfo func (m *UDF) Reset() { *m = UDF{} } func (*UDF) ProtoMessage() {} func (*UDF) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{78} + return fileDescriptor_9d0d1b17d3865563, []int{80} } func (m *UDF) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2263,7 +2319,7 @@ var xxx_messageInfo_UDF proto.InternalMessageInfo func (m *UDSink) Reset() { *m = UDSink{} } func (*UDSink) ProtoMessage() {} func (*UDSink) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{79} + return fileDescriptor_9d0d1b17d3865563, []int{81} } func (m *UDSink) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2291,7 +2347,7 @@ var xxx_messageInfo_UDSink proto.InternalMessageInfo func (m *UDSource) Reset() { *m = UDSource{} } func (*UDSource) ProtoMessage() {} func (*UDSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{80} + return fileDescriptor_9d0d1b17d3865563, []int{82} } func (m *UDSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2319,7 +2375,7 @@ var xxx_messageInfo_UDSource proto.InternalMessageInfo func (m *UDTransformer) Reset() { *m = UDTransformer{} } func (*UDTransformer) ProtoMessage() {} func (*UDTransformer) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{81} + return fileDescriptor_9d0d1b17d3865563, []int{83} } func (m *UDTransformer) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2347,7 +2403,7 @@ var xxx_messageInfo_UDTransformer proto.InternalMessageInfo func (m *Vertex) Reset() { *m = Vertex{} } func (*Vertex) ProtoMessage() {} func (*Vertex) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{82} + return fileDescriptor_9d0d1b17d3865563, []int{84} } func (m *Vertex) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2375,7 +2431,7 @@ var xxx_messageInfo_Vertex proto.InternalMessageInfo func (m *VertexInstance) Reset() { *m = VertexInstance{} } func (*VertexInstance) ProtoMessage() {} func (*VertexInstance) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{83} + return fileDescriptor_9d0d1b17d3865563, []int{85} } func (m *VertexInstance) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2403,7 +2459,7 @@ var xxx_messageInfo_VertexInstance proto.InternalMessageInfo func (m *VertexLimits) Reset() { *m = VertexLimits{} } func (*VertexLimits) ProtoMessage() {} func (*VertexLimits) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{84} + return fileDescriptor_9d0d1b17d3865563, []int{86} } func (m *VertexLimits) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2431,7 +2487,7 @@ var xxx_messageInfo_VertexLimits proto.InternalMessageInfo func (m *VertexList) Reset() { *m = VertexList{} } func (*VertexList) ProtoMessage() {} func (*VertexList) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{85} + return fileDescriptor_9d0d1b17d3865563, []int{87} } func (m *VertexList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2459,7 +2515,7 @@ var xxx_messageInfo_VertexList proto.InternalMessageInfo func (m *VertexSpec) Reset() { *m = VertexSpec{} } func (*VertexSpec) ProtoMessage() {} func (*VertexSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{86} + return fileDescriptor_9d0d1b17d3865563, []int{88} } func (m *VertexSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2487,7 +2543,7 @@ var xxx_messageInfo_VertexSpec proto.InternalMessageInfo func (m *VertexStatus) Reset() { *m = VertexStatus{} } func (*VertexStatus) ProtoMessage() {} func (*VertexStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{87} + return fileDescriptor_9d0d1b17d3865563, []int{89} } func (m *VertexStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2515,7 +2571,7 @@ var xxx_messageInfo_VertexStatus proto.InternalMessageInfo func (m *VertexTemplate) Reset() { *m = VertexTemplate{} } func (*VertexTemplate) ProtoMessage() {} func (*VertexTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{88} + return fileDescriptor_9d0d1b17d3865563, []int{90} } func (m *VertexTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2543,7 +2599,7 @@ var xxx_messageInfo_VertexTemplate proto.InternalMessageInfo func (m *Watermark) Reset() { *m = Watermark{} } func (*Watermark) ProtoMessage() {} func (*Watermark) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{89} + return fileDescriptor_9d0d1b17d3865563, []int{91} } func (m *Watermark) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2571,7 +2627,7 @@ var xxx_messageInfo_Watermark proto.InternalMessageInfo func (m *Window) Reset() { *m = Window{} } func (*Window) ProtoMessage() {} func (*Window) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{90} + return fileDescriptor_9d0d1b17d3865563, []int{92} } func (m *Window) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2602,6 +2658,7 @@ func init() { proto.RegisterType((*AbstractSink)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.AbstractSink") proto.RegisterType((*AbstractVertex)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.AbstractVertex") proto.RegisterType((*Authorization)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.Authorization") + proto.RegisterType((*Backoff)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.Backoff") proto.RegisterType((*BasicAuth)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.BasicAuth") proto.RegisterType((*Blackhole)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.Blackhole") proto.RegisterType((*BufferServiceConfig)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.BufferServiceConfig") @@ -2666,6 +2723,7 @@ func init() { proto.RegisterType((*RedisBufferService)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RedisBufferService") proto.RegisterType((*RedisConfig)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RedisConfig") proto.RegisterType((*RedisSettings)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RedisSettings") + proto.RegisterType((*RetryStrategy)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RetryStrategy") proto.RegisterType((*SASL)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.SASL") proto.RegisterType((*SASLPlain)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.SASLPlain") proto.RegisterType((*Scale)(nil), "github.com.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.Scale") @@ -2704,475 +2762,483 @@ func init() { } var fileDescriptor_9d0d1b17d3865563 = []byte{ - // 7488 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5b, 0x6c, 0x1d, 0xd7, - 0x79, 0xae, 0xf7, 0x8d, 0xdc, 0xfb, 0xdf, 0x24, 0x45, 0x2d, 0xc9, 0x32, 0x25, 0xcb, 0xa2, 0x32, - 0x8e, 0x7d, 0x94, 0x93, 0x84, 0x3c, 0xe6, 0xf1, 0x2d, 0x57, 0x9b, 0x9b, 0x14, 0x29, 0x4a, 0xa4, - 0xc4, 0xfc, 0x9b, 0x94, 0x9d, 0xf8, 0x24, 0x3e, 0xc3, 0x99, 0xc5, 0xcd, 0x31, 0x67, 0xcf, 0x6c, - 0xcf, 0xcc, 0xa6, 0x44, 0xe7, 0x1c, 0xe4, 0xf6, 0x60, 0x1f, 0x1c, 0x1c, 0x9c, 0x22, 0x4f, 0x01, - 0x8a, 0xb4, 0x68, 0x51, 0x20, 0x0f, 0x41, 0xfa, 0x50, 0xd4, 0x7d, 0x28, 0xd0, 0x4b, 0x8a, 0xa2, - 0x4d, 0x8a, 0x5e, 0xf2, 0x50, 0xa0, 0xee, 0x0b, 0xd1, 0xb0, 0xe8, 0x43, 0x0b, 0x34, 0x08, 0x1a, - 0xa0, 0x4d, 0x84, 0x00, 0x29, 0xd6, 0x6d, 0x6e, 0x7b, 0xb6, 0x44, 0xee, 0x21, 0x65, 0xb9, 0xf5, - 0xdb, 0xcc, 0x5a, 0xff, 0xfa, 0xfe, 0x35, 0xff, 0xba, 0xfd, 0xeb, 0x5f, 0xff, 0xfa, 0x07, 0x16, - 0x5b, 0x56, 0xb0, 0xd5, 0xdd, 0x98, 0x32, 0xdc, 0xf6, 0xb4, 0xd3, 0x6d, 0xeb, 0x1d, 0xcf, 0x7d, - 0x8d, 0x3f, 0x6c, 0xda, 0xee, 0xad, 0xe9, 0xce, 0x76, 0x6b, 0x5a, 0xef, 0x58, 0x7e, 0x94, 0xb2, - 0xf3, 0x94, 0x6e, 0x77, 0xb6, 0xf4, 0xa7, 0xa6, 0x5b, 0xd4, 0xa1, 0x9e, 0x1e, 0x50, 0x73, 0xaa, - 0xe3, 0xb9, 0x81, 0x4b, 0x9e, 0x8b, 0x80, 0xa6, 0x14, 0xd0, 0x94, 0x2a, 0x36, 0xd5, 0xd9, 0x6e, - 0x4d, 0x31, 0xa0, 0x28, 0x45, 0x01, 0x9d, 0xfb, 0x68, 0xac, 0x06, 0x2d, 0xb7, 0xe5, 0x4e, 0x73, - 0xbc, 0x8d, 0xee, 0x26, 0x7f, 0xe3, 0x2f, 0xfc, 0x49, 0xf0, 0x39, 0xa7, 0x6d, 0x3f, 0xef, 0x4f, - 0x59, 0x2e, 0xab, 0xd6, 0xb4, 0xe1, 0x7a, 0x74, 0x7a, 0xa7, 0xa7, 0x2e, 0xe7, 0x9e, 0x8e, 0x68, - 0xda, 0xba, 0xb1, 0x65, 0x39, 0xd4, 0xdb, 0x55, 0xdf, 0x32, 0xed, 0x51, 0xdf, 0xed, 0x7a, 0x06, - 0x3d, 0x54, 0x29, 0x7f, 0xba, 0x4d, 0x03, 0x3d, 0x8b, 0xd7, 0x74, 0xbf, 0x52, 0x5e, 0xd7, 0x09, - 0xac, 0x76, 0x2f, 0x9b, 0x67, 0xef, 0x55, 0xc0, 0x37, 0xb6, 0x68, 0x5b, 0x4f, 0x97, 0xd3, 0xbe, - 0x0b, 0x70, 0x6a, 0x76, 0xc3, 0x0f, 0x3c, 0xdd, 0x08, 0x56, 0x5d, 0x73, 0x8d, 0xb6, 0x3b, 0xb6, - 0x1e, 0x50, 0xb2, 0x0d, 0x55, 0x56, 0x37, 0x53, 0x0f, 0xf4, 0x89, 0xc2, 0xc5, 0xc2, 0xa5, 0xfa, - 0xcc, 0xec, 0xd4, 0x80, 0x6d, 0x31, 0xb5, 0x22, 0x81, 0x1a, 0x23, 0xfb, 0x7b, 0x93, 0x55, 0xf5, - 0x86, 0x21, 0x03, 0xf2, 0x8d, 0x02, 0x8c, 0x38, 0xae, 0x49, 0x9b, 0xd4, 0xa6, 0x46, 0xe0, 0x7a, - 0x13, 0xc5, 0x8b, 0xa5, 0x4b, 0xf5, 0x99, 0x2f, 0x0c, 0xcc, 0x31, 0xe3, 0x8b, 0xa6, 0xae, 0xc7, - 0x18, 0x5c, 0x76, 0x02, 0x6f, 0xb7, 0x71, 0xfa, 0x7b, 0x7b, 0x93, 0x0f, 0xed, 0xef, 0x4d, 0x8e, - 0xc4, 0xb3, 0x30, 0x51, 0x13, 0xb2, 0x0e, 0xf5, 0xc0, 0xb5, 0x99, 0xc8, 0x2c, 0xd7, 0xf1, 0x27, - 0x4a, 0xbc, 0x62, 0x17, 0xa6, 0x84, 0xb4, 0x19, 0xfb, 0x29, 0xd6, 0x5d, 0xa6, 0x76, 0x9e, 0x9a, - 0x5a, 0x0b, 0xc9, 0x1a, 0xa7, 0x24, 0x70, 0x3d, 0x4a, 0xf3, 0x31, 0x8e, 0x43, 0x28, 0x9c, 0xf0, - 0xa9, 0xd1, 0xf5, 0xac, 0x60, 0x77, 0xce, 0x75, 0x02, 0x7a, 0x3b, 0x98, 0x28, 0x73, 0x29, 0x3f, - 0x99, 0x05, 0xbd, 0xea, 0x9a, 0xcd, 0x24, 0x75, 0xe3, 0xd4, 0xfe, 0xde, 0xe4, 0x89, 0x54, 0x22, - 0xa6, 0x31, 0x89, 0x03, 0xe3, 0x56, 0x5b, 0x6f, 0xd1, 0xd5, 0xae, 0x6d, 0x37, 0xa9, 0xe1, 0xd1, - 0xc0, 0x9f, 0xa8, 0xf0, 0x4f, 0xb8, 0x94, 0xc5, 0x67, 0xd9, 0x35, 0x74, 0xfb, 0xc6, 0xc6, 0x6b, - 0xd4, 0x08, 0x90, 0x6e, 0x52, 0x8f, 0x3a, 0x06, 0x6d, 0x4c, 0xc8, 0x8f, 0x19, 0x5f, 0x4a, 0x21, - 0x61, 0x0f, 0x36, 0x59, 0x84, 0x93, 0x1d, 0xcf, 0x72, 0x79, 0x15, 0x6c, 0xdd, 0xf7, 0xaf, 0xeb, - 0x6d, 0x3a, 0x31, 0x74, 0xb1, 0x70, 0xa9, 0xd6, 0x38, 0x2b, 0x61, 0x4e, 0xae, 0xa6, 0x09, 0xb0, - 0xb7, 0x0c, 0xb9, 0x04, 0x55, 0x95, 0x38, 0x31, 0x7c, 0xb1, 0x70, 0xa9, 0x22, 0xfa, 0x8e, 0x2a, - 0x8b, 0x61, 0x2e, 0x59, 0x80, 0xaa, 0xbe, 0xb9, 0x69, 0x39, 0x8c, 0xb2, 0xca, 0x45, 0x78, 0x3e, - 0xeb, 0xd3, 0x66, 0x25, 0x8d, 0xc0, 0x51, 0x6f, 0x18, 0x96, 0x25, 0x57, 0x81, 0xf8, 0xd4, 0xdb, - 0xb1, 0x0c, 0x3a, 0x6b, 0x18, 0x6e, 0xd7, 0x09, 0x78, 0xdd, 0x6b, 0xbc, 0xee, 0xe7, 0x64, 0xdd, - 0x49, 0xb3, 0x87, 0x02, 0x33, 0x4a, 0x91, 0x17, 0x61, 0x5c, 0x0e, 0xbb, 0x48, 0x0a, 0xc0, 0x91, - 0x4e, 0x33, 0x41, 0x62, 0x2a, 0x0f, 0x7b, 0xa8, 0x89, 0x09, 0xe7, 0xf5, 0x6e, 0xe0, 0xb6, 0x19, - 0x64, 0x92, 0xe9, 0x9a, 0xbb, 0x4d, 0x9d, 0x89, 0xfa, 0xc5, 0xc2, 0xa5, 0x6a, 0xe3, 0xe2, 0xfe, - 0xde, 0xe4, 0xf9, 0xd9, 0xbb, 0xd0, 0xe1, 0x5d, 0x51, 0xc8, 0x0d, 0xa8, 0x99, 0x8e, 0xbf, 0xea, - 0xda, 0x96, 0xb1, 0x3b, 0x31, 0xc2, 0x2b, 0xf8, 0x94, 0xfc, 0xd4, 0xda, 0xfc, 0xf5, 0xa6, 0xc8, - 0xb8, 0xb3, 0x37, 0x79, 0xbe, 0x77, 0x76, 0x9c, 0x0a, 0xf3, 0x31, 0xc2, 0x20, 0x2b, 0x1c, 0x70, - 0xce, 0x75, 0x36, 0xad, 0xd6, 0xc4, 0x28, 0x6f, 0x8d, 0x8b, 0x7d, 0x3a, 0xf4, 0xfc, 0xf5, 0xa6, - 0xa0, 0x6b, 0x8c, 0x4a, 0x76, 0xe2, 0x15, 0x23, 0x04, 0x62, 0xc2, 0x98, 0x9a, 0x57, 0xe7, 0x6c, - 0xdd, 0x6a, 0xfb, 0x13, 0x63, 0xbc, 0xf3, 0x7e, 0xb0, 0x0f, 0x26, 0xc6, 0x89, 0x1b, 0x67, 0xe4, - 0xa7, 0x8c, 0x25, 0x92, 0x7d, 0x4c, 0x61, 0x9e, 0x7b, 0x01, 0x4e, 0xf6, 0xcc, 0x0d, 0x64, 0x1c, - 0x4a, 0xdb, 0x74, 0x97, 0x4f, 0x7d, 0x35, 0x64, 0x8f, 0xe4, 0x34, 0x54, 0x76, 0x74, 0xbb, 0x4b, - 0x27, 0x8a, 0x3c, 0x4d, 0xbc, 0x7c, 0xbc, 0xf8, 0x7c, 0x41, 0xfb, 0xf5, 0x12, 0x8c, 0xa8, 0x19, - 0xa7, 0x69, 0x39, 0xdb, 0xe4, 0x25, 0x28, 0xd9, 0x6e, 0x4b, 0xce, 0x9b, 0x9f, 0x1c, 0x78, 0x16, - 0x5b, 0x76, 0x5b, 0x8d, 0xe1, 0xfd, 0xbd, 0xc9, 0xd2, 0xb2, 0xdb, 0x42, 0x86, 0x48, 0x0c, 0xa8, - 0x6c, 0xeb, 0x9b, 0xdb, 0x3a, 0xaf, 0x43, 0x7d, 0xa6, 0x31, 0x30, 0xf4, 0x35, 0x86, 0xc2, 0xea, - 0xda, 0xa8, 0xed, 0xef, 0x4d, 0x56, 0xf8, 0x2b, 0x0a, 0x6c, 0xe2, 0x42, 0x6d, 0xc3, 0xd6, 0x8d, - 0xed, 0x2d, 0xd7, 0xa6, 0x13, 0xa5, 0x9c, 0x8c, 0x1a, 0x0a, 0x49, 0x34, 0x73, 0xf8, 0x8a, 0x11, - 0x0f, 0x62, 0xc0, 0x50, 0xd7, 0xf4, 0x2d, 0x67, 0x5b, 0xce, 0x81, 0x2f, 0x0c, 0xcc, 0x6d, 0x7d, - 0x9e, 0x7f, 0x13, 0xec, 0xef, 0x4d, 0x0e, 0x89, 0x67, 0x94, 0xd0, 0xda, 0x8f, 0xea, 0x30, 0xa6, - 0x1a, 0xe9, 0x26, 0xf5, 0x02, 0x7a, 0x9b, 0x5c, 0x84, 0xb2, 0xc3, 0x86, 0x26, 0x6f, 0xe4, 0xc6, - 0x88, 0xec, 0x2e, 0x65, 0x3e, 0x24, 0x79, 0x0e, 0xab, 0x99, 0xe8, 0x2a, 0x52, 0xe0, 0x83, 0xd7, - 0xac, 0xc9, 0x61, 0x44, 0xcd, 0xc4, 0x33, 0x4a, 0x68, 0xf2, 0x0a, 0x94, 0xf9, 0xc7, 0x0b, 0x51, - 0x7f, 0x6a, 0x70, 0x16, 0xec, 0xd3, 0xab, 0xec, 0x0b, 0xf8, 0x87, 0x73, 0x50, 0xd6, 0x15, 0xbb, - 0xe6, 0xa6, 0x14, 0xec, 0x27, 0x73, 0x08, 0x76, 0x41, 0x74, 0xc5, 0xf5, 0xf9, 0x05, 0x64, 0x88, - 0xe4, 0xff, 0x17, 0xe0, 0xa4, 0xe1, 0x3a, 0x81, 0xce, 0x54, 0x0d, 0xb5, 0xc8, 0x4e, 0x54, 0x38, - 0x9f, 0xab, 0x03, 0xf3, 0x99, 0x4b, 0x23, 0x36, 0x1e, 0x66, 0x6b, 0x46, 0x4f, 0x32, 0xf6, 0xf2, - 0x26, 0xbf, 0x5c, 0x80, 0x87, 0xd9, 0x5c, 0xde, 0x43, 0xcc, 0x57, 0xa0, 0xa3, 0xad, 0xd5, 0xd9, - 0xfd, 0xbd, 0xc9, 0x87, 0x97, 0xb2, 0x98, 0x61, 0x76, 0x1d, 0x58, 0xed, 0x4e, 0xe9, 0xbd, 0x6a, - 0x09, 0x5f, 0xdd, 0xea, 0x33, 0xcb, 0x47, 0xa9, 0xea, 0x34, 0x1e, 0x95, 0x5d, 0x39, 0x4b, 0xb3, - 0xc3, 0xac, 0x5a, 0x90, 0xcb, 0x30, 0xbc, 0xe3, 0xda, 0xdd, 0x36, 0xf5, 0x27, 0xaa, 0x7c, 0x8a, - 0x3d, 0x97, 0x35, 0xc5, 0xde, 0xe4, 0x24, 0x8d, 0x13, 0x12, 0x7e, 0x58, 0xbc, 0xfb, 0xa8, 0xca, - 0x12, 0x0b, 0x86, 0x6c, 0xab, 0x6d, 0x05, 0x3e, 0x5f, 0x38, 0xeb, 0x33, 0x97, 0x07, 0xfe, 0x2c, - 0x31, 0x44, 0x97, 0x39, 0x98, 0x18, 0x35, 0xe2, 0x19, 0x25, 0x03, 0x36, 0x15, 0xfa, 0x86, 0x6e, - 0x8b, 0x85, 0xb5, 0x3e, 0xf3, 0xe9, 0xc1, 0x87, 0x0d, 0x43, 0x69, 0x8c, 0xca, 0x6f, 0xaa, 0xf0, - 0x57, 0x14, 0xd8, 0xe4, 0xf3, 0x30, 0x96, 0x68, 0x4d, 0x7f, 0xa2, 0xce, 0xa5, 0xf3, 0x58, 0x96, - 0x74, 0x42, 0xaa, 0x68, 0xe5, 0x49, 0xf4, 0x10, 0x1f, 0x53, 0x60, 0xe4, 0x1a, 0x54, 0x7d, 0xcb, - 0xa4, 0x86, 0xee, 0xf9, 0x13, 0x23, 0x07, 0x01, 0x1e, 0x97, 0xc0, 0xd5, 0xa6, 0x2c, 0x86, 0x21, - 0x00, 0x99, 0x02, 0xe8, 0xe8, 0x5e, 0x60, 0x09, 0x45, 0x75, 0x94, 0x2b, 0x4d, 0x63, 0xfb, 0x7b, - 0x93, 0xb0, 0x1a, 0xa6, 0x62, 0x8c, 0x82, 0xd1, 0xb3, 0xb2, 0x4b, 0x4e, 0xa7, 0x1b, 0x88, 0x85, - 0xb5, 0x26, 0xe8, 0x9b, 0x61, 0x2a, 0xc6, 0x28, 0xc8, 0x77, 0x0a, 0xf0, 0x68, 0xf4, 0xda, 0x3b, - 0xc8, 0x4e, 0x1c, 0xf9, 0x20, 0x9b, 0xdc, 0xdf, 0x9b, 0x7c, 0xb4, 0xd9, 0x9f, 0x25, 0xde, 0xad, - 0x3e, 0xda, 0x4b, 0x30, 0x3a, 0xdb, 0x0d, 0xb6, 0x5c, 0xcf, 0x7a, 0x83, 0x2b, 0xdd, 0x64, 0x01, - 0x2a, 0x01, 0x57, 0x9e, 0xc4, 0xba, 0xfc, 0x44, 0x96, 0xa8, 0x85, 0x22, 0x7b, 0x8d, 0xee, 0x2a, - 0x6d, 0x40, 0xac, 0x8f, 0x42, 0x99, 0x12, 0xc5, 0xb5, 0x5f, 0x2b, 0x40, 0xad, 0xa1, 0xfb, 0x96, - 0xc1, 0xe0, 0xc9, 0x1c, 0x94, 0xbb, 0x3e, 0xf5, 0x0e, 0x07, 0xca, 0x67, 0xe9, 0x75, 0x9f, 0x7a, - 0xc8, 0x0b, 0x93, 0x1b, 0x50, 0xed, 0xe8, 0xbe, 0x7f, 0xcb, 0xf5, 0x4c, 0xb9, 0xd2, 0x1c, 0x10, - 0x48, 0x68, 0xc5, 0xb2, 0x28, 0x86, 0x20, 0x5a, 0x1d, 0xa2, 0xa5, 0x56, 0xfb, 0x49, 0x01, 0x4e, - 0x35, 0xba, 0x9b, 0x9b, 0xd4, 0x93, 0x4a, 0xa0, 0x54, 0xaf, 0x28, 0x54, 0x3c, 0x6a, 0x5a, 0xbe, - 0xac, 0xfb, 0xfc, 0xc0, 0x4d, 0x87, 0x0c, 0x45, 0x6a, 0x73, 0x5c, 0x5e, 0x3c, 0x01, 0x05, 0x3a, - 0xe9, 0x42, 0xed, 0x35, 0x1a, 0xf8, 0x81, 0x47, 0xf5, 0xb6, 0xfc, 0xba, 0x2b, 0x03, 0xb3, 0xba, - 0x4a, 0x83, 0x26, 0x47, 0x8a, 0x2b, 0x8f, 0x61, 0x22, 0x46, 0x9c, 0xb4, 0xef, 0x56, 0x60, 0x64, - 0xce, 0x6d, 0x6f, 0x58, 0x0e, 0x35, 0x2f, 0x9b, 0x2d, 0x4a, 0x5e, 0x85, 0x32, 0x35, 0x5b, 0x54, - 0x7e, 0xed, 0xe0, 0xeb, 0x2c, 0x03, 0x8b, 0xb4, 0x05, 0xf6, 0x86, 0x1c, 0x98, 0x2c, 0xc3, 0xd8, - 0xa6, 0xe7, 0xb6, 0xc5, 0xd4, 0xb5, 0xb6, 0xdb, 0x91, 0xaa, 0x62, 0xe3, 0x83, 0x6a, 0x3a, 0x58, - 0x48, 0xe4, 0xde, 0xd9, 0x9b, 0x84, 0xe8, 0x0d, 0x53, 0x65, 0xc9, 0xcb, 0x30, 0x11, 0xa5, 0x84, - 0x63, 0x78, 0x8e, 0x69, 0xef, 0x5c, 0x55, 0xa8, 0x34, 0xce, 0xef, 0xef, 0x4d, 0x4e, 0x2c, 0xf4, - 0xa1, 0xc1, 0xbe, 0xa5, 0xc9, 0x9b, 0x05, 0x18, 0x8f, 0x32, 0xc5, 0xbc, 0x2a, 0x35, 0x84, 0x23, - 0x9a, 0xb0, 0xf9, 0x36, 0x67, 0x21, 0xc5, 0x02, 0x7b, 0x98, 0x92, 0x05, 0x18, 0x09, 0xdc, 0x98, - 0xbc, 0x2a, 0x5c, 0x5e, 0x9a, 0xda, 0x97, 0xaf, 0xb9, 0x7d, 0xa5, 0x95, 0x28, 0x47, 0x10, 0xce, - 0xa8, 0xf7, 0x94, 0xa4, 0x86, 0xb8, 0xa4, 0xce, 0xed, 0xef, 0x4d, 0x9e, 0x59, 0xcb, 0xa4, 0xc0, - 0x3e, 0x25, 0xc9, 0x57, 0x0a, 0x30, 0xa6, 0xb2, 0xa4, 0x8c, 0x86, 0x8f, 0x52, 0x46, 0x84, 0xf5, - 0x88, 0xb5, 0x04, 0x03, 0x4c, 0x31, 0xd4, 0x7e, 0x5a, 0x86, 0x5a, 0x38, 0xb3, 0x91, 0xc7, 0xa1, - 0xc2, 0x77, 0xdc, 0x52, 0x61, 0x0d, 0x97, 0x2c, 0xbe, 0x31, 0x47, 0x91, 0x47, 0x9e, 0x80, 0x61, - 0xc3, 0x6d, 0xb7, 0x75, 0xc7, 0xe4, 0x56, 0x94, 0x5a, 0xa3, 0xce, 0x56, 0xea, 0x39, 0x91, 0x84, - 0x2a, 0x8f, 0x9c, 0x87, 0xb2, 0xee, 0xb5, 0x84, 0x41, 0xa3, 0x26, 0xe6, 0xa3, 0x59, 0xaf, 0xe5, - 0x23, 0x4f, 0x25, 0x1f, 0x83, 0x12, 0x75, 0x76, 0x26, 0xca, 0xfd, 0x55, 0x81, 0xcb, 0xce, 0xce, - 0x4d, 0xdd, 0x6b, 0xd4, 0x65, 0x1d, 0x4a, 0x97, 0x9d, 0x1d, 0x64, 0x65, 0xc8, 0x32, 0x0c, 0x53, - 0x67, 0x87, 0xb5, 0xbd, 0xb4, 0x34, 0x7c, 0xa0, 0x4f, 0x71, 0x46, 0x22, 0xb5, 0xe2, 0x50, 0xa1, - 0x90, 0xc9, 0xa8, 0x20, 0xc8, 0x67, 0x61, 0x44, 0xe8, 0x16, 0x2b, 0xac, 0x4d, 0xfc, 0x89, 0x21, - 0x0e, 0x39, 0xd9, 0x5f, 0x39, 0xe1, 0x74, 0x91, 0x65, 0x27, 0x96, 0xe8, 0x63, 0x02, 0x8a, 0x7c, - 0x16, 0x6a, 0x6a, 0x23, 0xa8, 0x5a, 0x36, 0xd3, 0x28, 0xa2, 0x76, 0x8f, 0x48, 0x5f, 0xef, 0x5a, - 0x1e, 0x6d, 0x53, 0x27, 0xf0, 0x1b, 0x27, 0xd5, 0x36, 0x59, 0xe5, 0xfa, 0x18, 0xa1, 0x91, 0x8d, - 0x5e, 0xeb, 0x8e, 0x30, 0x4d, 0x3c, 0xde, 0x67, 0x56, 0x1f, 0xc0, 0xb4, 0xf3, 0x05, 0x38, 0x11, - 0x9a, 0x5f, 0xe4, 0x0e, 0x5e, 0x18, 0x2b, 0x9e, 0x66, 0xc5, 0x97, 0x92, 0x59, 0x77, 0xf6, 0x26, - 0x1f, 0xcb, 0xd8, 0xc3, 0x47, 0x04, 0x98, 0x06, 0xd3, 0xfe, 0xa0, 0x04, 0xbd, 0x6a, 0x77, 0x52, - 0x68, 0x85, 0xa3, 0x16, 0x5a, 0xfa, 0x83, 0xc4, 0xf4, 0xf9, 0xbc, 0x2c, 0x96, 0xff, 0xa3, 0xb2, - 0x1a, 0xa6, 0x74, 0xd4, 0x0d, 0xf3, 0xa0, 0x8c, 0x1d, 0xed, 0xad, 0x32, 0x8c, 0xcd, 0xeb, 0xb4, - 0xed, 0x3a, 0xf7, 0xdc, 0x84, 0x14, 0x1e, 0x88, 0x4d, 0xc8, 0x25, 0xa8, 0x7a, 0xb4, 0x63, 0x5b, - 0x86, 0xee, 0xf3, 0xa6, 0x97, 0x46, 0x3f, 0x94, 0x69, 0x18, 0xe6, 0xf6, 0xd9, 0x7c, 0x96, 0x1e, - 0xc8, 0xcd, 0x67, 0xf9, 0xdd, 0xdf, 0x7c, 0x6a, 0x5f, 0x29, 0x02, 0x57, 0x54, 0xc8, 0x45, 0x28, - 0xb3, 0x45, 0x38, 0x6d, 0xf2, 0xe0, 0x1d, 0x87, 0xe7, 0x90, 0x73, 0x50, 0x0c, 0x5c, 0x39, 0xf2, - 0x40, 0xe6, 0x17, 0xd7, 0x5c, 0x2c, 0x06, 0x2e, 0x79, 0x03, 0xc0, 0x70, 0x1d, 0xd3, 0x52, 0xb6, - 0xf0, 0x7c, 0x1f, 0xb6, 0xe0, 0x7a, 0xb7, 0x74, 0xcf, 0x9c, 0x0b, 0x11, 0xc5, 0xf6, 0x23, 0x7a, - 0xc7, 0x18, 0x37, 0xf2, 0x02, 0x0c, 0xb9, 0xce, 0x42, 0xd7, 0xb6, 0xb9, 0x40, 0x6b, 0x8d, 0xff, - 0xc2, 0xf6, 0x84, 0x37, 0x78, 0xca, 0x9d, 0xbd, 0xc9, 0xb3, 0x42, 0xbf, 0x65, 0x6f, 0x2f, 0x79, - 0x56, 0x60, 0x39, 0xad, 0x66, 0xe0, 0xe9, 0x01, 0x6d, 0xed, 0xa2, 0x2c, 0xa6, 0x7d, 0xbd, 0x00, - 0xf5, 0x05, 0xeb, 0x36, 0x35, 0x5f, 0xb2, 0x1c, 0xd3, 0xbd, 0x45, 0x10, 0x86, 0x6c, 0xea, 0xb4, - 0x82, 0x2d, 0xd9, 0xfb, 0xa7, 0x62, 0x63, 0x2d, 0x3c, 0x42, 0x89, 0xea, 0xdf, 0xa6, 0x81, 0xce, - 0x46, 0xdf, 0x7c, 0x57, 0x1a, 0xf9, 0xc5, 0xa6, 0x94, 0x23, 0xa0, 0x44, 0x22, 0xd3, 0x50, 0x13, - 0xda, 0xa7, 0xe5, 0xb4, 0xb8, 0x0c, 0xab, 0xd1, 0xa4, 0xd7, 0x54, 0x19, 0x18, 0xd1, 0x68, 0xbb, - 0x70, 0xb2, 0x47, 0x0c, 0xc4, 0x84, 0x72, 0xa0, 0xb7, 0xd4, 0xfc, 0xba, 0x30, 0xb0, 0x80, 0xd7, - 0xf4, 0x56, 0x4c, 0xb8, 0x7c, 0x8d, 0x5f, 0xd3, 0xd9, 0x1a, 0xcf, 0xd0, 0xb5, 0x9f, 0x17, 0xa0, - 0xba, 0xd0, 0x75, 0x0c, 0xbe, 0x37, 0xba, 0xb7, 0x29, 0x4c, 0x29, 0x0c, 0xc5, 0x4c, 0x85, 0xa1, - 0x0b, 0x43, 0xdb, 0xb7, 0x42, 0x85, 0xa2, 0x3e, 0xb3, 0x32, 0x78, 0xaf, 0x90, 0x55, 0x9a, 0xba, - 0xc6, 0xf1, 0xc4, 0x49, 0xcd, 0x98, 0xac, 0xd0, 0xd0, 0xb5, 0x97, 0x38, 0x53, 0xc9, 0xec, 0xdc, - 0xc7, 0xa0, 0x1e, 0x23, 0x3b, 0x94, 0xd1, 0xf6, 0x77, 0xca, 0x30, 0xb4, 0xd8, 0x6c, 0xce, 0xae, - 0x2e, 0x91, 0x67, 0xa0, 0x2e, 0x8d, 0xf8, 0xd7, 0x23, 0x19, 0x84, 0x67, 0x38, 0xcd, 0x28, 0x0b, - 0xe3, 0x74, 0x4c, 0x1d, 0xf3, 0xa8, 0x6e, 0xb7, 0xe5, 0x60, 0x09, 0xd5, 0x31, 0x64, 0x89, 0x28, - 0xf2, 0x88, 0x0e, 0x63, 0x6c, 0x87, 0xc7, 0x44, 0x28, 0x76, 0x6f, 0x72, 0xd8, 0x1c, 0x70, 0x7f, - 0xc7, 0x95, 0xc4, 0xf5, 0x04, 0x00, 0xa6, 0x00, 0xc9, 0xf3, 0x50, 0xd5, 0xbb, 0xc1, 0x16, 0x57, - 0xa0, 0xc5, 0xd8, 0x38, 0xcf, 0xcf, 0x38, 0x64, 0xda, 0x9d, 0xbd, 0xc9, 0x91, 0x6b, 0xd8, 0x78, - 0x46, 0xbd, 0x63, 0x48, 0xcd, 0x2a, 0xa7, 0x76, 0x8c, 0xb2, 0x72, 0x95, 0x43, 0x57, 0x6e, 0x35, - 0x01, 0x80, 0x29, 0x40, 0xf2, 0x0a, 0x8c, 0x6c, 0xd3, 0xdd, 0x40, 0xdf, 0x90, 0x0c, 0x86, 0x0e, - 0xc3, 0x60, 0x9c, 0xa9, 0x70, 0xd7, 0x62, 0xc5, 0x31, 0x01, 0x46, 0x7c, 0x38, 0xbd, 0x4d, 0xbd, - 0x0d, 0xea, 0xb9, 0x72, 0xf7, 0x29, 0x99, 0x0c, 0x1f, 0x86, 0xc9, 0xc4, 0xfe, 0xde, 0xe4, 0xe9, - 0x6b, 0x19, 0x30, 0x98, 0x09, 0xae, 0xfd, 0xac, 0x08, 0x27, 0x16, 0xc5, 0x29, 0xaa, 0xeb, 0x89, - 0x45, 0x98, 0x9c, 0x85, 0x92, 0xd7, 0xe9, 0xf2, 0x9e, 0x53, 0x12, 0x76, 0x52, 0x5c, 0x5d, 0x47, - 0x96, 0x46, 0x5e, 0x86, 0xaa, 0x29, 0xa7, 0x0c, 0xb9, 0xf9, 0x3d, 0xec, 0x44, 0xc3, 0x17, 0x41, - 0xf5, 0x86, 0x21, 0x1a, 0xd3, 0xf4, 0xdb, 0x7e, 0xab, 0x69, 0xbd, 0x41, 0xe5, 0x7e, 0x90, 0x6b, - 0xfa, 0x2b, 0x22, 0x09, 0x55, 0x1e, 0x5b, 0x55, 0xb7, 0xe9, 0xae, 0xd8, 0x0d, 0x95, 0xa3, 0x55, - 0xf5, 0x9a, 0x4c, 0xc3, 0x30, 0x97, 0x4c, 0xaa, 0xc1, 0xc2, 0x7a, 0x41, 0x59, 0xec, 0xe4, 0x6f, - 0xb2, 0x04, 0x39, 0x6e, 0xd8, 0x94, 0xf9, 0x9a, 0x15, 0x04, 0xd4, 0x93, 0xcd, 0x38, 0xd0, 0x94, - 0x79, 0x95, 0x23, 0xa0, 0x44, 0x22, 0x1f, 0x86, 0x1a, 0x07, 0x6f, 0xd8, 0xee, 0x06, 0x6f, 0xb8, - 0x9a, 0xd8, 0xd3, 0xdf, 0x54, 0x89, 0x18, 0xe5, 0x6b, 0xbf, 0x28, 0xc2, 0x99, 0x45, 0x1a, 0x08, - 0xad, 0x66, 0x9e, 0x76, 0x6c, 0x77, 0x97, 0xa9, 0x96, 0x48, 0x5f, 0x27, 0x2f, 0x02, 0x58, 0xfe, - 0x46, 0x73, 0xc7, 0xe0, 0xe3, 0x40, 0x8c, 0xe1, 0x8b, 0x72, 0x48, 0xc2, 0x52, 0xb3, 0x21, 0x73, - 0xee, 0x24, 0xde, 0x30, 0x56, 0x26, 0xda, 0x5e, 0x15, 0xef, 0xb2, 0xbd, 0x6a, 0x02, 0x74, 0x22, - 0x05, 0xb5, 0xc4, 0x29, 0xff, 0xbb, 0x62, 0x73, 0x18, 0xdd, 0x34, 0x06, 0x93, 0x47, 0x65, 0x74, - 0x60, 0xdc, 0xa4, 0x9b, 0x7a, 0xd7, 0x0e, 0x42, 0xa5, 0x5a, 0x0e, 0xe2, 0x83, 0xeb, 0xe5, 0xe1, - 0x09, 0xef, 0x7c, 0x0a, 0x09, 0x7b, 0xb0, 0xb5, 0xdf, 0x2d, 0xc1, 0xb9, 0x45, 0x1a, 0x84, 0x16, - 0x17, 0x39, 0x3b, 0x36, 0x3b, 0xd4, 0x60, 0xad, 0xf0, 0x66, 0x01, 0x86, 0x6c, 0x7d, 0x83, 0xda, - 0x6c, 0xf5, 0x62, 0x5f, 0xf3, 0xea, 0xc0, 0x0b, 0x41, 0x7f, 0x2e, 0x53, 0xcb, 0x9c, 0x43, 0x6a, - 0x69, 0x10, 0x89, 0x28, 0xd9, 0xb3, 0x49, 0xdd, 0xb0, 0xbb, 0x7e, 0x40, 0xbd, 0x55, 0xd7, 0x0b, - 0xa4, 0x3e, 0x19, 0x4e, 0xea, 0x73, 0x51, 0x16, 0xc6, 0xe9, 0xc8, 0x0c, 0x80, 0x61, 0x5b, 0xd4, - 0x09, 0x78, 0x29, 0x31, 0xae, 0x88, 0x6a, 0xdf, 0xb9, 0x30, 0x07, 0x63, 0x54, 0x8c, 0x55, 0xdb, - 0x75, 0xac, 0xc0, 0x15, 0xac, 0xca, 0x49, 0x56, 0x2b, 0x51, 0x16, 0xc6, 0xe9, 0x78, 0x31, 0x1a, - 0x78, 0x96, 0xe1, 0xf3, 0x62, 0x95, 0x54, 0xb1, 0x28, 0x0b, 0xe3, 0x74, 0x6c, 0xcd, 0x8b, 0x7d, - 0xff, 0xa1, 0xd6, 0xbc, 0x6f, 0xd7, 0xe0, 0x42, 0x42, 0xac, 0x81, 0x1e, 0xd0, 0xcd, 0xae, 0xdd, - 0xa4, 0x81, 0x6a, 0xc0, 0x01, 0xd7, 0xc2, 0xff, 0x1b, 0xb5, 0xbb, 0xf0, 0xdd, 0x30, 0x8e, 0xa6, - 0xdd, 0x7b, 0x2a, 0x78, 0xa0, 0xb6, 0x9f, 0x86, 0x9a, 0xa3, 0x07, 0x3e, 0x1f, 0xb8, 0x72, 0x8c, - 0x86, 0x6a, 0xd8, 0x75, 0x95, 0x81, 0x11, 0x0d, 0x59, 0x85, 0xd3, 0x52, 0xc4, 0x97, 0x6f, 0x77, - 0x5c, 0x2f, 0xa0, 0x9e, 0x28, 0x2b, 0x97, 0x53, 0x59, 0xf6, 0xf4, 0x4a, 0x06, 0x0d, 0x66, 0x96, - 0x24, 0x2b, 0x70, 0xca, 0x10, 0xe7, 0xd9, 0xd4, 0x76, 0x75, 0x53, 0x01, 0x0a, 0x03, 0x57, 0xb8, - 0x35, 0x9a, 0xeb, 0x25, 0xc1, 0xac, 0x72, 0xe9, 0xde, 0x3c, 0x34, 0x50, 0x6f, 0x1e, 0x1e, 0xa4, - 0x37, 0x57, 0x07, 0xeb, 0xcd, 0xb5, 0x83, 0xf5, 0x66, 0x26, 0x79, 0xd6, 0x8f, 0xa8, 0xc7, 0xd4, - 0x13, 0xb1, 0xc2, 0xc6, 0xdc, 0x25, 0x42, 0xc9, 0x37, 0x33, 0x68, 0x30, 0xb3, 0x24, 0xd9, 0x80, - 0x73, 0x22, 0xfd, 0xb2, 0x63, 0x78, 0xbb, 0x1d, 0xb6, 0xf0, 0xc4, 0x70, 0xeb, 0x09, 0x0b, 0xe3, - 0xb9, 0x66, 0x5f, 0x4a, 0xbc, 0x0b, 0x0a, 0xf9, 0x04, 0x8c, 0x8a, 0x56, 0x5a, 0xd1, 0x3b, 0x1c, - 0x56, 0x38, 0x4f, 0x3c, 0x2c, 0x61, 0x47, 0xe7, 0xe2, 0x99, 0x98, 0xa4, 0x25, 0xb3, 0x70, 0xa2, - 0xb3, 0x63, 0xb0, 0xc7, 0xa5, 0xcd, 0xeb, 0x94, 0x9a, 0xd4, 0xe4, 0xa7, 0x35, 0xb5, 0xc6, 0x23, - 0xca, 0xd0, 0xb1, 0x9a, 0xcc, 0xc6, 0x34, 0x3d, 0x79, 0x1e, 0x46, 0xfc, 0x40, 0xf7, 0x02, 0x69, - 0xd6, 0x9b, 0x18, 0x13, 0xce, 0x25, 0xca, 0xea, 0xd5, 0x8c, 0xe5, 0x61, 0x82, 0x32, 0x73, 0xbd, - 0x38, 0x71, 0x7c, 0xeb, 0x45, 0x9e, 0xd9, 0xea, 0x4f, 0x8b, 0x70, 0x71, 0x91, 0x06, 0x2b, 0xae, - 0x23, 0x8d, 0xa2, 0x59, 0xcb, 0xfe, 0x81, 0x6c, 0xa2, 0xc9, 0x45, 0xbb, 0x78, 0xa4, 0x8b, 0x76, - 0xe9, 0x88, 0x16, 0xed, 0xf2, 0x31, 0x2e, 0xda, 0xbf, 0x5f, 0x84, 0x47, 0x12, 0x92, 0x5c, 0x75, - 0x4d, 0x35, 0xe1, 0xbf, 0x2f, 0xc0, 0x03, 0x08, 0xf0, 0x8e, 0xd0, 0x3b, 0xf9, 0xb1, 0x56, 0x4a, - 0xe3, 0xf9, 0x5a, 0x5a, 0xe3, 0x79, 0x25, 0xcf, 0xca, 0x97, 0xc1, 0xe1, 0x40, 0x2b, 0xde, 0x55, - 0x20, 0x9e, 0x3c, 0x84, 0x13, 0xa6, 0x9f, 0x98, 0xd2, 0x13, 0x7a, 0xaf, 0x61, 0x0f, 0x05, 0x66, - 0x94, 0x22, 0x4d, 0x78, 0xd8, 0xa7, 0x4e, 0x60, 0x39, 0xd4, 0x4e, 0xc2, 0x09, 0x6d, 0xe8, 0x31, - 0x09, 0xf7, 0x70, 0x33, 0x8b, 0x08, 0xb3, 0xcb, 0xe6, 0x99, 0x07, 0xfe, 0x1c, 0xb8, 0xca, 0x29, - 0x44, 0x73, 0x64, 0x1a, 0xcb, 0x9b, 0x69, 0x8d, 0xe5, 0xd5, 0xfc, 0xed, 0x36, 0x98, 0xb6, 0x32, - 0x03, 0xc0, 0x5b, 0x21, 0xae, 0xae, 0x84, 0x8b, 0x34, 0x86, 0x39, 0x18, 0xa3, 0x62, 0x0b, 0x90, - 0x92, 0x73, 0x5c, 0x53, 0x09, 0x17, 0xa0, 0x66, 0x3c, 0x13, 0x93, 0xb4, 0x7d, 0xb5, 0x9d, 0xca, - 0xc0, 0xda, 0xce, 0x55, 0x20, 0x09, 0xc3, 0xa3, 0xc0, 0x1b, 0x4a, 0x3a, 0x4f, 0x2e, 0xf5, 0x50, - 0x60, 0x46, 0xa9, 0x3e, 0x5d, 0x79, 0xf8, 0x68, 0xbb, 0x72, 0x75, 0xf0, 0xae, 0x4c, 0x5e, 0x85, - 0xb3, 0x9c, 0x95, 0x94, 0x4f, 0x12, 0x58, 0xe8, 0x3d, 0x1f, 0x90, 0xc0, 0x67, 0xb1, 0x1f, 0x21, - 0xf6, 0xc7, 0x60, 0xed, 0x63, 0x78, 0xd4, 0x64, 0xcc, 0x75, 0xbb, 0xbf, 0x4e, 0x34, 0x97, 0x41, - 0x83, 0x99, 0x25, 0x59, 0x17, 0x0b, 0x58, 0x37, 0xd4, 0x37, 0x6c, 0x6a, 0x4a, 0xe7, 0xd1, 0xb0, - 0x8b, 0xad, 0x2d, 0x37, 0x65, 0x0e, 0xc6, 0xa8, 0xb2, 0xd4, 0x94, 0x91, 0x43, 0xaa, 0x29, 0x8b, - 0xdc, 0x4a, 0xbf, 0x99, 0xd0, 0x86, 0xa4, 0xae, 0x13, 0xba, 0x03, 0xcf, 0xa5, 0x09, 0xb0, 0xb7, - 0x0c, 0xd7, 0x12, 0x0d, 0xcf, 0xea, 0x04, 0x7e, 0x12, 0x6b, 0x2c, 0xa5, 0x25, 0x66, 0xd0, 0x60, - 0x66, 0x49, 0xa6, 0x9f, 0x6f, 0x51, 0xdd, 0x0e, 0xb6, 0x92, 0x80, 0x27, 0x92, 0xfa, 0xf9, 0x95, - 0x5e, 0x12, 0xcc, 0x2a, 0x97, 0xb9, 0x20, 0x8d, 0x3f, 0x98, 0x6a, 0xd5, 0x57, 0x4b, 0x70, 0x76, - 0x91, 0x06, 0xa1, 0x5f, 0xcd, 0xfb, 0x66, 0x94, 0x77, 0xc1, 0x8c, 0xf2, 0xad, 0x0a, 0x9c, 0x5a, - 0xa4, 0x41, 0x8f, 0x36, 0xf6, 0x9f, 0x54, 0xfc, 0x2b, 0x70, 0x2a, 0x72, 0xe5, 0x6a, 0x06, 0xae, - 0x27, 0xd6, 0xf2, 0xd4, 0x6e, 0xb9, 0xd9, 0x4b, 0x82, 0x59, 0xe5, 0xc8, 0x67, 0xe1, 0x11, 0xbe, - 0xd4, 0x3b, 0x2d, 0x61, 0x9f, 0x15, 0xc6, 0x84, 0xd8, 0x65, 0x84, 0x49, 0x09, 0xf9, 0x48, 0x33, - 0x9b, 0x0c, 0xfb, 0x95, 0x27, 0x5f, 0x82, 0x91, 0x8e, 0xd5, 0xa1, 0xb6, 0xe5, 0x70, 0xfd, 0x2c, - 0xb7, 0x4b, 0xc8, 0x6a, 0x0c, 0x2c, 0xda, 0xc0, 0xc5, 0x53, 0x31, 0xc1, 0x30, 0xb3, 0xa7, 0x56, - 0x8f, 0xb1, 0xa7, 0xfe, 0x4b, 0x11, 0x86, 0x17, 0x3d, 0xb7, 0xdb, 0x69, 0xec, 0x92, 0x16, 0x0c, - 0xdd, 0xe2, 0x87, 0x67, 0xf2, 0x68, 0x6a, 0x70, 0x77, 0x68, 0x71, 0x06, 0x17, 0xa9, 0x44, 0xe2, - 0x1d, 0x25, 0x3c, 0xeb, 0xc4, 0xdb, 0x74, 0x97, 0x9a, 0xf2, 0x0c, 0x2d, 0xec, 0xc4, 0xd7, 0x58, - 0x22, 0x8a, 0x3c, 0xd2, 0x86, 0x13, 0xba, 0x6d, 0xbb, 0xb7, 0xa8, 0xb9, 0xac, 0x07, 0xd4, 0xa1, - 0xbe, 0x3a, 0x92, 0x3c, 0xac, 0x59, 0x9a, 0x9f, 0xeb, 0xcf, 0x26, 0xa1, 0x30, 0x8d, 0x4d, 0x5e, - 0x83, 0x61, 0x3f, 0x70, 0x3d, 0xa5, 0x6c, 0xd5, 0x67, 0xe6, 0x06, 0x6f, 0xf4, 0xc6, 0x67, 0x9a, - 0x02, 0x4a, 0xd8, 0xec, 0xe5, 0x0b, 0x2a, 0x06, 0xda, 0x37, 0x0b, 0x00, 0x57, 0xd6, 0xd6, 0x56, - 0xe5, 0xf1, 0x82, 0x09, 0x65, 0xbd, 0x1b, 0x1e, 0x54, 0x0e, 0x7e, 0x20, 0x98, 0xf0, 0x87, 0x94, - 0x67, 0x78, 0xdd, 0x60, 0x0b, 0x39, 0x3a, 0xf9, 0x10, 0x0c, 0x4b, 0x05, 0x59, 0x8a, 0x3d, 0x74, - 0x2d, 0x90, 0x4a, 0x34, 0xaa, 0x7c, 0xed, 0xb7, 0x8a, 0x00, 0x4b, 0xa6, 0x4d, 0x9b, 0xca, 0x83, - 0xbd, 0x16, 0x6c, 0x79, 0xd4, 0xdf, 0x72, 0x6d, 0x73, 0xc0, 0xd3, 0x54, 0x6e, 0xf3, 0x5f, 0x53, - 0x20, 0x18, 0xe1, 0x11, 0x13, 0x46, 0xfc, 0x80, 0x76, 0x96, 0x9c, 0x80, 0x7a, 0x3b, 0xba, 0x3d, - 0xe0, 0x21, 0xca, 0xb8, 0xb0, 0x8b, 0x44, 0x38, 0x98, 0x40, 0x25, 0x3a, 0xd4, 0x2d, 0xc7, 0x10, - 0x03, 0xa4, 0xb1, 0x3b, 0x60, 0x47, 0x3a, 0xc1, 0x76, 0x1c, 0x4b, 0x11, 0x0c, 0xc6, 0x31, 0xb5, - 0x1f, 0x17, 0xe1, 0x0c, 0xe7, 0xc7, 0xaa, 0x91, 0xf0, 0xc7, 0x24, 0xff, 0xb3, 0xe7, 0xb6, 0xdd, - 0x7f, 0x3b, 0x18, 0x6b, 0x71, 0x59, 0x6b, 0x85, 0x06, 0x7a, 0xa4, 0xcf, 0x45, 0x69, 0xb1, 0x2b, - 0x76, 0x5d, 0x28, 0xfb, 0x6c, 0xbe, 0x12, 0xd2, 0x6b, 0x0e, 0xdc, 0x85, 0xb2, 0x3f, 0x80, 0xcf, - 0x5e, 0xe1, 0xa9, 0x31, 0x9f, 0xb5, 0x38, 0x3b, 0xf2, 0xbf, 0x61, 0xc8, 0x0f, 0xf4, 0xa0, 0xab, - 0x86, 0xe6, 0xfa, 0x51, 0x33, 0xe6, 0xe0, 0xd1, 0x3c, 0x22, 0xde, 0x51, 0x32, 0xd5, 0x7e, 0x5c, - 0x80, 0x73, 0xd9, 0x05, 0x97, 0x2d, 0x3f, 0x20, 0xff, 0xa3, 0x47, 0xec, 0x07, 0x6c, 0x71, 0x56, - 0x9a, 0x0b, 0x3d, 0x74, 0xc8, 0x56, 0x29, 0x31, 0x91, 0x07, 0x50, 0xb1, 0x02, 0xda, 0x56, 0xfb, - 0xcb, 0x1b, 0x47, 0xfc, 0xe9, 0xb1, 0xa5, 0x9d, 0x71, 0x41, 0xc1, 0x4c, 0x7b, 0xab, 0xd8, 0xef, - 0x93, 0xf9, 0xf2, 0x61, 0x27, 0x7d, 0x7e, 0xaf, 0xe5, 0xf3, 0xf9, 0x4d, 0x56, 0xa8, 0xd7, 0xf5, - 0xf7, 0x7f, 0xf5, 0xba, 0xfe, 0xde, 0xc8, 0xef, 0xfa, 0x9b, 0x12, 0x43, 0x5f, 0x0f, 0xe0, 0x77, - 0x4a, 0x70, 0xfe, 0x6e, 0xdd, 0x86, 0xad, 0x67, 0xb2, 0x77, 0xe6, 0x5d, 0xcf, 0xee, 0xde, 0x0f, - 0xc9, 0x0c, 0x54, 0x3a, 0x5b, 0xba, 0xaf, 0x94, 0x32, 0xb5, 0x61, 0xa9, 0xac, 0xb2, 0xc4, 0x3b, - 0x6c, 0xd2, 0xe0, 0xca, 0x1c, 0x7f, 0x45, 0x41, 0xca, 0xa6, 0xe3, 0x36, 0xf5, 0xfd, 0xc8, 0x26, - 0x10, 0x4e, 0xc7, 0x2b, 0x22, 0x19, 0x55, 0x3e, 0x09, 0x60, 0x48, 0x98, 0x98, 0xe5, 0xca, 0x34, - 0xb8, 0x23, 0x57, 0x86, 0x9b, 0x78, 0xf4, 0x51, 0xf2, 0xb4, 0x42, 0xf2, 0x22, 0x53, 0x50, 0x0e, - 0x22, 0xa7, 0x5d, 0xb5, 0x35, 0x2f, 0x67, 0xe8, 0xa7, 0x9c, 0x8e, 0x6d, 0xec, 0xdd, 0x0d, 0x6e, - 0x54, 0x37, 0xe5, 0xf9, 0xb9, 0xe5, 0x3a, 0x5c, 0x21, 0x2b, 0x45, 0x1b, 0xfb, 0x1b, 0x3d, 0x14, - 0x98, 0x51, 0x4a, 0xfb, 0xab, 0x2a, 0x9c, 0xc9, 0xee, 0x0f, 0x4c, 0x6e, 0x3b, 0xd4, 0xf3, 0x19, - 0x76, 0x21, 0x29, 0xb7, 0x9b, 0x22, 0x19, 0x55, 0xfe, 0x7b, 0xda, 0xe1, 0xec, 0x5b, 0x05, 0x38, - 0xeb, 0xc9, 0x33, 0xa2, 0xfb, 0xe1, 0x74, 0xf6, 0x98, 0x30, 0x67, 0xf4, 0x61, 0x88, 0xfd, 0xeb, - 0x42, 0x7e, 0xa3, 0x00, 0x13, 0xed, 0x94, 0x9d, 0xe3, 0x18, 0x2f, 0x8c, 0x71, 0xaf, 0xf8, 0x95, - 0x3e, 0xfc, 0xb0, 0x6f, 0x4d, 0xc8, 0x97, 0xa0, 0xde, 0x61, 0xfd, 0xc2, 0x0f, 0xa8, 0x63, 0xa8, - 0x3b, 0x63, 0x83, 0x8f, 0xa4, 0xd5, 0x08, 0x4b, 0xb9, 0xa2, 0x09, 0xfd, 0x20, 0x96, 0x81, 0x71, - 0x8e, 0x0f, 0xf8, 0x0d, 0xb1, 0x4b, 0x50, 0xf5, 0x69, 0x10, 0x58, 0x4e, 0x4b, 0xec, 0x37, 0x6a, - 0x62, 0xac, 0x34, 0x65, 0x1a, 0x86, 0xb9, 0xe4, 0xc3, 0x50, 0xe3, 0x47, 0x4e, 0xb3, 0x5e, 0xcb, - 0x9f, 0xa8, 0x71, 0x77, 0xb1, 0x51, 0xe1, 0x00, 0x27, 0x13, 0x31, 0xca, 0x27, 0x4f, 0xc3, 0xc8, - 0x06, 0x1f, 0xbe, 0xf2, 0xd2, 0xb0, 0xb0, 0x71, 0x71, 0x6d, 0xad, 0x11, 0x4b, 0xc7, 0x04, 0x15, - 0x99, 0x01, 0xa0, 0xe1, 0xb9, 0x5c, 0xda, 0x9e, 0x15, 0x9d, 0xd8, 0x61, 0x8c, 0x8a, 0x3c, 0x06, - 0xa5, 0xc0, 0xf6, 0xb9, 0x0d, 0xab, 0x1a, 0x6d, 0x41, 0xd7, 0x96, 0x9b, 0xc8, 0xd2, 0xb5, 0x5f, - 0x14, 0xe0, 0x44, 0xea, 0x72, 0x09, 0x2b, 0xd2, 0xf5, 0x6c, 0x39, 0x8d, 0x84, 0x45, 0xd6, 0x71, - 0x19, 0x59, 0x3a, 0x79, 0x55, 0xaa, 0xe5, 0xc5, 0x9c, 0xf1, 0x11, 0xae, 0xeb, 0x81, 0xcf, 0xf4, - 0xf0, 0x1e, 0x8d, 0x9c, 0x1f, 0xf3, 0x45, 0xf5, 0x91, 0xeb, 0x40, 0xec, 0x98, 0x2f, 0xca, 0xc3, - 0x04, 0x65, 0xca, 0xe0, 0x57, 0x3e, 0x88, 0xc1, 0x4f, 0xfb, 0x7a, 0x31, 0x26, 0x01, 0xa9, 0xd9, - 0xdf, 0x43, 0x02, 0x4f, 0xb2, 0x05, 0x34, 0x5c, 0xdc, 0x6b, 0xf1, 0xf5, 0x8f, 0x2f, 0xc6, 0x32, - 0x97, 0xbc, 0x24, 0x64, 0x5f, 0xca, 0x79, 0x0b, 0x75, 0x6d, 0xb9, 0x29, 0xbc, 0xab, 0x54, 0xab, - 0x85, 0x4d, 0x50, 0x3e, 0xa6, 0x26, 0xd0, 0xfe, 0xac, 0x04, 0xf5, 0xab, 0xee, 0xc6, 0x7b, 0xc4, - 0x83, 0x3a, 0x7b, 0x99, 0x2a, 0xbe, 0x8b, 0xcb, 0xd4, 0x3a, 0x3c, 0x12, 0x04, 0x76, 0x93, 0x1a, - 0xae, 0x63, 0xfa, 0xb3, 0x9b, 0x01, 0xf5, 0x16, 0x2c, 0xc7, 0xf2, 0xb7, 0xa8, 0x29, 0x8f, 0x93, - 0x1e, 0xdd, 0xdf, 0x9b, 0x7c, 0x64, 0x6d, 0x6d, 0x39, 0x8b, 0x04, 0xfb, 0x95, 0xe5, 0xd3, 0x86, - 0x6e, 0x6c, 0xbb, 0x9b, 0x9b, 0xfc, 0xa6, 0x8c, 0xf4, 0xb9, 0x11, 0xd3, 0x46, 0x2c, 0x1d, 0x13, - 0x54, 0xda, 0xdb, 0x45, 0xa8, 0x85, 0x37, 0xdf, 0xc9, 0x13, 0x30, 0xbc, 0xe1, 0xb9, 0xdb, 0xd4, - 0x13, 0x27, 0x77, 0xf2, 0xa6, 0x4c, 0x43, 0x24, 0xa1, 0xca, 0x23, 0x8f, 0x43, 0x25, 0x70, 0x3b, - 0x96, 0x91, 0x36, 0xa8, 0xad, 0xb1, 0x44, 0x14, 0x79, 0xc7, 0xd7, 0xc1, 0x9f, 0x4c, 0xa8, 0x76, - 0xb5, 0xbe, 0xca, 0xd8, 0x2b, 0x50, 0xf6, 0x75, 0xdf, 0x96, 0xeb, 0x69, 0x8e, 0x4b, 0xe4, 0xb3, - 0xcd, 0x65, 0x79, 0x89, 0x7c, 0xb6, 0xb9, 0x8c, 0x1c, 0x54, 0xfb, 0x69, 0x11, 0xea, 0x42, 0x6e, - 0x62, 0x56, 0x38, 0x4a, 0xc9, 0xbd, 0xc0, 0x5d, 0x29, 0xfc, 0x6e, 0x9b, 0x7a, 0xdc, 0xcc, 0x24, - 0x27, 0xb9, 0xf8, 0xf9, 0x40, 0x94, 0x19, 0xba, 0x53, 0x44, 0x49, 0x4a, 0xf4, 0xe5, 0x63, 0x14, - 0x7d, 0xe5, 0x40, 0xa2, 0x1f, 0x3a, 0x0e, 0xd1, 0xbf, 0x59, 0x84, 0xda, 0xb2, 0xb5, 0x49, 0x8d, - 0x5d, 0xc3, 0xe6, 0x77, 0x02, 0x4d, 0x6a, 0xd3, 0x80, 0x2e, 0x7a, 0xba, 0x41, 0x57, 0xa9, 0x67, - 0xf1, 0xc8, 0x30, 0x6c, 0x7c, 0xf0, 0x19, 0x48, 0xde, 0x09, 0x9c, 0xef, 0x43, 0x83, 0x7d, 0x4b, - 0x93, 0x25, 0x18, 0x31, 0xa9, 0x6f, 0x79, 0xd4, 0x5c, 0x8d, 0x6d, 0x54, 0x9e, 0x50, 0x4b, 0xcd, - 0x7c, 0x2c, 0xef, 0xce, 0xde, 0xe4, 0xa8, 0x32, 0x50, 0x8a, 0x1d, 0x4b, 0xa2, 0x28, 0x1b, 0xf2, - 0x1d, 0xbd, 0xeb, 0x67, 0xd5, 0x31, 0x36, 0xe4, 0x57, 0xb3, 0x49, 0xb0, 0x5f, 0x59, 0xad, 0x02, - 0xa5, 0x65, 0xb7, 0xa5, 0xbd, 0x55, 0x82, 0x30, 0x84, 0x10, 0xf9, 0x3f, 0x05, 0xa8, 0xeb, 0x8e, - 0xe3, 0x06, 0x32, 0x3c, 0x8f, 0x38, 0x81, 0xc7, 0xdc, 0x91, 0x8a, 0xa6, 0x66, 0x23, 0x50, 0x71, - 0x78, 0x1b, 0x1e, 0x28, 0xc7, 0x72, 0x30, 0xce, 0x9b, 0x74, 0x53, 0xe7, 0xc9, 0x2b, 0xf9, 0x6b, - 0x71, 0x80, 0xd3, 0xe3, 0x73, 0x9f, 0x86, 0xf1, 0x74, 0x65, 0x0f, 0x73, 0x1c, 0x94, 0xeb, 0x60, - 0xbe, 0x08, 0x10, 0xf9, 0x94, 0xdc, 0x07, 0x23, 0x96, 0x95, 0x30, 0x62, 0x2d, 0x0e, 0x2e, 0xe0, - 0xb0, 0xd2, 0x7d, 0x0d, 0x57, 0xaf, 0xa7, 0x0c, 0x57, 0x4b, 0x47, 0xc1, 0xec, 0xee, 0xc6, 0xaa, - 0xdf, 0x2c, 0xc0, 0x78, 0x44, 0x2c, 0x6f, 0xc8, 0x3e, 0x07, 0xa3, 0x1e, 0xd5, 0xcd, 0x86, 0x1e, - 0x18, 0x5b, 0xdc, 0xd5, 0xbb, 0xc0, 0x7d, 0xb3, 0x4f, 0xee, 0xef, 0x4d, 0x8e, 0x62, 0x3c, 0x03, - 0x93, 0x74, 0x44, 0x87, 0x3a, 0x4b, 0x58, 0xb3, 0xda, 0xd4, 0xed, 0x06, 0x03, 0x5a, 0x4d, 0xf9, - 0x86, 0x05, 0x23, 0x18, 0x8c, 0x63, 0x6a, 0xef, 0x14, 0x60, 0x2c, 0x5e, 0xe1, 0x63, 0xb7, 0xa8, - 0x6d, 0x25, 0x2d, 0x6a, 0x73, 0x47, 0xd0, 0x26, 0x7d, 0xac, 0x68, 0x3f, 0xab, 0xc6, 0x3f, 0x8d, - 0x5b, 0xce, 0xe2, 0xc6, 0x82, 0xc2, 0x5d, 0x8d, 0x05, 0xef, 0xfd, 0xa8, 0x31, 0xfd, 0xb4, 0xdc, - 0xf2, 0x03, 0xac, 0xe5, 0xbe, 0x9b, 0xa1, 0x67, 0x62, 0xe1, 0x53, 0x86, 0x72, 0x84, 0x4f, 0x69, - 0x87, 0xe1, 0x53, 0x86, 0x8f, 0x6c, 0xd2, 0x39, 0x48, 0x08, 0x95, 0xea, 0x7d, 0x0d, 0xa1, 0x52, - 0x3b, 0xae, 0x10, 0x2a, 0x90, 0x37, 0x84, 0xca, 0xd7, 0x0a, 0x30, 0x66, 0x26, 0x6e, 0xcc, 0x72, - 0xdb, 0x42, 0x9e, 0xa5, 0x26, 0x79, 0x01, 0x57, 0x5c, 0x99, 0x4a, 0xa6, 0x61, 0x8a, 0xa5, 0xf6, - 0xdb, 0x95, 0xf8, 0x3a, 0x70, 0xbf, 0x4d, 0xd5, 0xcf, 0x26, 0x4d, 0xd5, 0x17, 0xd3, 0xa6, 0xea, - 0x13, 0x31, 0x2f, 0xd2, 0xb8, 0xb9, 0xfa, 0x23, 0xb1, 0xe9, 0x91, 0xcd, 0x49, 0xa3, 0x91, 0xa4, - 0x33, 0xa6, 0xc8, 0x8f, 0x40, 0xd5, 0x57, 0xc1, 0x1e, 0xc5, 0xc6, 0x26, 0x6a, 0x17, 0x15, 0x88, - 0x31, 0xa4, 0x60, 0x9a, 0xb8, 0x47, 0x75, 0xdf, 0x75, 0xd2, 0x9a, 0x38, 0xf2, 0x54, 0x94, 0xb9, - 0x71, 0x93, 0xf9, 0xd0, 0x3d, 0x4c, 0xe6, 0x3a, 0xd4, 0x6d, 0xdd, 0x0f, 0xd6, 0x3b, 0xa6, 0x1e, - 0x50, 0x53, 0x8e, 0xb7, 0xff, 0x7a, 0xb0, 0xb5, 0x8a, 0xad, 0x7f, 0x91, 0x42, 0xb8, 0x1c, 0xc1, - 0x60, 0x1c, 0x93, 0x98, 0x30, 0xc2, 0x5e, 0xf9, 0x68, 0x30, 0x67, 0x55, 0x08, 0x80, 0xc3, 0xf0, - 0x08, 0x2d, 0x3d, 0xcb, 0x31, 0x1c, 0x4c, 0xa0, 0xf6, 0xb1, 0xaa, 0xd7, 0x06, 0xb1, 0xaa, 0x93, - 0x4f, 0x08, 0x65, 0x63, 0x57, 0x35, 0x18, 0xb7, 0xc6, 0x8d, 0x46, 0x5e, 0x85, 0x18, 0xcf, 0xc4, - 0x24, 0xad, 0xf6, 0xb5, 0x1a, 0xd4, 0xaf, 0xeb, 0x81, 0xb5, 0x43, 0xf9, 0x11, 0xd0, 0xf1, 0xd8, - 0xe1, 0x7f, 0xa5, 0x00, 0x67, 0x92, 0x7e, 0x7e, 0xc7, 0x68, 0x8c, 0xe7, 0x51, 0x43, 0x30, 0x93, - 0x1b, 0xf6, 0xa9, 0x05, 0x37, 0xcb, 0xf7, 0xb8, 0x0d, 0x1e, 0xb7, 0x59, 0xbe, 0xd9, 0x8f, 0x21, - 0xf6, 0xaf, 0xcb, 0x7b, 0xc5, 0x2c, 0xff, 0x60, 0x47, 0x75, 0x4b, 0x1d, 0x1a, 0x0c, 0x3f, 0x30, - 0x87, 0x06, 0xd5, 0x07, 0x42, 0x53, 0xeb, 0xc4, 0x0e, 0x0d, 0x6a, 0x39, 0x9d, 0x57, 0xa4, 0x6b, - 0xbc, 0x40, 0xeb, 0x77, 0xf8, 0xc0, 0x6f, 0xb5, 0x2b, 0x63, 0x2e, 0x53, 0x70, 0x36, 0x74, 0xdf, - 0x32, 0xe4, 0x9a, 0x99, 0x23, 0x8a, 0xa5, 0x0a, 0xf7, 0x25, 0xce, 0xb8, 0xf9, 0x2b, 0x0a, 0xec, - 0x28, 0xac, 0x58, 0x31, 0x57, 0x58, 0x31, 0x32, 0x07, 0x65, 0x87, 0x6d, 0xbd, 0x4b, 0x87, 0x0e, - 0x24, 0x76, 0xfd, 0x1a, 0xdd, 0x45, 0x5e, 0x58, 0x7b, 0xbb, 0x08, 0xc0, 0x3e, 0xff, 0x60, 0xe6, - 0xfb, 0x0f, 0xc1, 0xb0, 0xdf, 0xe5, 0x1b, 0x6d, 0xb9, 0xda, 0x47, 0x1e, 0x3f, 0x22, 0x19, 0x55, - 0x3e, 0x79, 0x1c, 0x2a, 0xaf, 0x77, 0x69, 0x57, 0x9d, 0x45, 0x87, 0xba, 0xde, 0x67, 0x58, 0x22, - 0x8a, 0xbc, 0xe3, 0x33, 0xc5, 0x29, 0x33, 0x7f, 0xe5, 0xb8, 0xcc, 0xfc, 0x35, 0x18, 0xbe, 0xee, - 0x72, 0x07, 0x42, 0xed, 0x9f, 0x8a, 0x00, 0x91, 0x83, 0x16, 0xf9, 0x66, 0x01, 0x1e, 0x0e, 0x07, - 0x5c, 0x20, 0x54, 0x76, 0x1e, 0x38, 0x36, 0xb7, 0xc9, 0x3f, 0x6b, 0xb0, 0xf3, 0x19, 0x68, 0x35, - 0x8b, 0x1d, 0x66, 0xd7, 0x82, 0x20, 0x54, 0x69, 0xbb, 0x13, 0xec, 0xce, 0x5b, 0x9e, 0xec, 0x81, - 0x99, 0x7e, 0x80, 0x97, 0x25, 0x8d, 0x28, 0x2a, 0xf7, 0x95, 0x7c, 0x10, 0xa9, 0x1c, 0x0c, 0x71, - 0xc8, 0x16, 0x54, 0x1d, 0xf7, 0x55, 0x9f, 0x89, 0x43, 0x76, 0xc7, 0x17, 0x07, 0x17, 0xb9, 0x10, - 0xab, 0x30, 0x11, 0xcb, 0x17, 0x1c, 0x76, 0xa4, 0xb0, 0xbf, 0x51, 0x84, 0x53, 0x19, 0x72, 0x20, - 0x2f, 0xc2, 0xb8, 0xf4, 0x85, 0x8b, 0x22, 0x28, 0x17, 0xa2, 0x08, 0xca, 0xcd, 0x54, 0x1e, 0xf6, - 0x50, 0x93, 0x57, 0x01, 0x74, 0xc3, 0xa0, 0xbe, 0xbf, 0xe2, 0x9a, 0x4a, 0x99, 0x7d, 0x61, 0x7f, - 0x6f, 0x12, 0x66, 0xc3, 0xd4, 0x3b, 0x7b, 0x93, 0x1f, 0xcd, 0x72, 0x6f, 0x4d, 0xc9, 0x39, 0x2a, - 0x80, 0x31, 0x48, 0xf2, 0x05, 0x00, 0xb1, 0x6f, 0x0b, 0x6f, 0xe0, 0xdf, 0xc3, 0xd8, 0x31, 0xa5, - 0x62, 0x1d, 0x4d, 0x7d, 0xa6, 0xab, 0x3b, 0x81, 0x15, 0xec, 0x8a, 0x80, 0x27, 0x37, 0x43, 0x14, - 0x8c, 0x21, 0x6a, 0x7f, 0x52, 0x84, 0xaa, 0x32, 0xb3, 0xde, 0x07, 0xdb, 0x5a, 0x2b, 0x61, 0x5b, - 0x3b, 0x22, 0x87, 0xd6, 0x2c, 0xcb, 0x9a, 0x9b, 0xb2, 0xac, 0x2d, 0xe6, 0x67, 0x75, 0x77, 0xbb, - 0xda, 0x77, 0x8a, 0x30, 0xa6, 0x48, 0xf3, 0x5a, 0xd5, 0x3e, 0x05, 0x27, 0xc4, 0x41, 0xf4, 0x8a, - 0x7e, 0x5b, 0xc4, 0x7e, 0xe1, 0x02, 0x2b, 0x0b, 0x1f, 0xd2, 0x46, 0x32, 0x0b, 0xd3, 0xb4, 0xac, - 0x5b, 0x8b, 0xa4, 0x75, 0xb6, 0x09, 0x11, 0x47, 0x57, 0x62, 0xb3, 0xc4, 0xbb, 0x75, 0x23, 0x95, - 0x87, 0x3d, 0xd4, 0x69, 0xb3, 0x5e, 0xf9, 0x18, 0xcc, 0x7a, 0x7f, 0x5d, 0x80, 0x91, 0x48, 0x5e, - 0xc7, 0x6e, 0xd4, 0xdb, 0x4c, 0x1a, 0xf5, 0x66, 0x73, 0x77, 0x87, 0x3e, 0x26, 0xbd, 0xff, 0x37, - 0x0c, 0x09, 0xbf, 0x6a, 0xb2, 0x01, 0xe7, 0xac, 0x4c, 0xef, 0xb0, 0xd8, 0x6c, 0x13, 0x5e, 0x14, - 0x5e, 0xea, 0x4b, 0x89, 0x77, 0x41, 0x21, 0x5d, 0xa8, 0xee, 0x50, 0x2f, 0xb0, 0x0c, 0xaa, 0xbe, - 0x6f, 0x31, 0xb7, 0x4a, 0x26, 0x0d, 0x97, 0xa1, 0x4c, 0x6f, 0x4a, 0x06, 0x18, 0xb2, 0x22, 0x1b, - 0x50, 0xa1, 0x66, 0x8b, 0xaa, 0x68, 0x3c, 0x39, 0x63, 0x5d, 0x86, 0xf2, 0x64, 0x6f, 0x3e, 0x0a, - 0x68, 0xe2, 0x43, 0xcd, 0x56, 0x07, 0x53, 0xb2, 0x1f, 0x0e, 0xae, 0x60, 0x85, 0x47, 0x5c, 0xd1, - 0x45, 0xfd, 0x30, 0x09, 0x23, 0x3e, 0x64, 0x3b, 0xb4, 0x90, 0x55, 0x8e, 0x68, 0xf2, 0xb8, 0x8b, - 0x7d, 0xcc, 0x87, 0xda, 0x2d, 0x3d, 0xa0, 0x5e, 0x5b, 0xf7, 0xb6, 0xe5, 0x6e, 0x63, 0xf0, 0x2f, - 0x7c, 0x49, 0x21, 0x45, 0x5f, 0x18, 0x26, 0x61, 0xc4, 0x87, 0xb8, 0x50, 0x0b, 0xa4, 0xfa, 0xac, - 0xcc, 0x80, 0x83, 0x33, 0x55, 0x8a, 0xb8, 0x2f, 0xfd, 0xab, 0xd5, 0x2b, 0x46, 0x3c, 0xc8, 0x4e, - 0x22, 0x0e, 0xb0, 0x88, 0xfe, 0xdc, 0xc8, 0x61, 0x4e, 0x96, 0x50, 0xd1, 0x72, 0x93, 0x1d, 0x4f, - 0x58, 0x7b, 0xbb, 0x12, 0x4d, 0xcb, 0xf7, 0xdb, 0xc8, 0xf5, 0x74, 0xd2, 0xc8, 0x75, 0x21, 0x6d, - 0xe4, 0x4a, 0x9d, 0x6f, 0x1e, 0xde, 0x23, 0x33, 0x65, 0x5e, 0x2a, 0x1f, 0x83, 0x79, 0xe9, 0x29, - 0xa8, 0xef, 0xf0, 0x99, 0x40, 0x84, 0xf6, 0xa9, 0xf0, 0x65, 0x84, 0xcf, 0xec, 0x37, 0xa3, 0x64, - 0x8c, 0xd3, 0xb0, 0x22, 0xf2, 0xcf, 0x07, 0x61, 0x6c, 0x54, 0x59, 0xa4, 0x19, 0x25, 0x63, 0x9c, - 0x86, 0x3b, 0x73, 0x59, 0xce, 0xb6, 0x28, 0x30, 0xcc, 0x0b, 0x08, 0x67, 0x2e, 0x95, 0x88, 0x51, - 0x3e, 0xb9, 0x04, 0xd5, 0xae, 0xb9, 0x29, 0x68, 0xab, 0x9c, 0x96, 0x6b, 0x98, 0xeb, 0xf3, 0x0b, - 0x32, 0xd4, 0x90, 0xca, 0x65, 0x35, 0x69, 0xeb, 0x1d, 0x95, 0xc1, 0xf7, 0x86, 0xb2, 0x26, 0x2b, - 0x51, 0x32, 0xc6, 0x69, 0xc8, 0xc7, 0x61, 0xcc, 0xa3, 0x66, 0xd7, 0xa0, 0x61, 0x29, 0x61, 0x9d, - 0x22, 0xe2, 0x17, 0x0f, 0xf1, 0x1c, 0x4c, 0x51, 0xf6, 0x31, 0x92, 0xd5, 0x07, 0x72, 0x3d, 0xfd, - 0x51, 0x01, 0x48, 0xaf, 0xf3, 0x33, 0xd9, 0x82, 0x21, 0x87, 0x5b, 0xbf, 0x72, 0x47, 0x53, 0x8e, - 0x19, 0xd1, 0xc4, 0xb4, 0x24, 0x13, 0x24, 0x3e, 0x71, 0xa0, 0x4a, 0x6f, 0x07, 0xd4, 0x73, 0xc2, - 0xcb, 0x10, 0x47, 0x13, 0xb9, 0x59, 0xec, 0x06, 0x24, 0x32, 0x86, 0x3c, 0xb4, 0x9f, 0x14, 0xa1, - 0x1e, 0xa3, 0xbb, 0xd7, 0xa6, 0x92, 0xdf, 0xc7, 0x16, 0x46, 0xa7, 0x75, 0xcf, 0x96, 0x23, 0x2c, - 0x76, 0x1f, 0x5b, 0x66, 0xe1, 0x32, 0xc6, 0xe9, 0xc8, 0x0c, 0x40, 0x5b, 0xf7, 0x03, 0xea, 0xf1, - 0xd5, 0x37, 0x75, 0x0b, 0x7a, 0x25, 0xcc, 0xc1, 0x18, 0x15, 0xb9, 0x28, 0x63, 0x6f, 0x97, 0x93, - 0x51, 0xeb, 0xfa, 0x04, 0xd6, 0xae, 0x1c, 0x41, 0x60, 0x6d, 0xd2, 0x82, 0x71, 0x55, 0x6b, 0x95, - 0x7b, 0xb8, 0x98, 0x66, 0x62, 0xff, 0x92, 0x82, 0xc0, 0x1e, 0x50, 0xed, 0xed, 0x02, 0x8c, 0x26, - 0x4c, 0x1e, 0x22, 0xde, 0x9c, 0x72, 0xdd, 0x4f, 0xc4, 0x9b, 0x8b, 0x79, 0xdc, 0x3f, 0x09, 0x43, - 0x42, 0x40, 0x69, 0x8f, 0x3c, 0x21, 0x42, 0x94, 0xb9, 0x6c, 0x2e, 0x93, 0x46, 0xd5, 0xf4, 0x5c, - 0x26, 0xad, 0xae, 0xa8, 0xf2, 0x85, 0xad, 0x5e, 0xd4, 0xae, 0xd7, 0x56, 0x2f, 0xd2, 0x31, 0xa4, - 0xd0, 0xfe, 0xad, 0x04, 0xdc, 0x7f, 0x85, 0x3c, 0x07, 0xb5, 0x36, 0x35, 0xb6, 0x74, 0xc7, 0xf2, - 0x55, 0xbc, 0x49, 0xb6, 0xbb, 0xad, 0xad, 0xa8, 0xc4, 0x3b, 0x0c, 0x60, 0xb6, 0xb9, 0xcc, 0x5d, - 0xc4, 0x23, 0x5a, 0x62, 0xc0, 0x50, 0xcb, 0xf7, 0xf5, 0x8e, 0x95, 0xfb, 0xf8, 0x54, 0xc4, 0xf7, - 0x13, 0x83, 0x48, 0x3c, 0xa3, 0x84, 0x26, 0x06, 0x54, 0x3a, 0xb6, 0x6e, 0x39, 0xb9, 0x7f, 0x70, - 0xc2, 0xbe, 0x60, 0x95, 0x21, 0x09, 0x93, 0x0e, 0x7f, 0x44, 0x81, 0x4d, 0xba, 0x50, 0xf7, 0x0d, - 0x4f, 0x6f, 0xfb, 0x5b, 0xfa, 0xcc, 0x33, 0xcf, 0xe6, 0x56, 0x92, 0x22, 0x56, 0x62, 0xce, 0x9e, - 0xc3, 0xd9, 0x95, 0xe6, 0x95, 0xd9, 0x99, 0x67, 0x9e, 0xc5, 0x38, 0x9f, 0x38, 0xdb, 0x67, 0x9e, - 0x9a, 0x91, 0xfd, 0xfe, 0xc8, 0xd9, 0x3e, 0xf3, 0xd4, 0x0c, 0xc6, 0xf9, 0x68, 0xff, 0x5a, 0x80, - 0x5a, 0x48, 0x4b, 0xd6, 0x01, 0xd8, 0x08, 0x94, 0x11, 0xf9, 0x0e, 0x15, 0x1d, 0x9f, 0xef, 0x8a, - 0xd7, 0xc3, 0xc2, 0x18, 0x03, 0xca, 0x08, 0x59, 0x58, 0x3c, 0xea, 0x90, 0x85, 0xd3, 0x50, 0xdb, - 0xd2, 0x1d, 0xd3, 0xdf, 0xd2, 0xb7, 0xc5, 0x44, 0x14, 0x0b, 0xe2, 0x79, 0x45, 0x65, 0x60, 0x44, - 0xa3, 0xfd, 0xd1, 0x10, 0x88, 0x33, 0x4f, 0x36, 0x54, 0x4c, 0xcb, 0x17, 0x4e, 0xb7, 0x05, 0x5e, - 0x32, 0x1c, 0x2a, 0xf3, 0x32, 0x1d, 0x43, 0x0a, 0x72, 0x16, 0x4a, 0x6d, 0xcb, 0x91, 0x27, 0x1e, - 0xdc, 0xe0, 0xb5, 0x62, 0x39, 0xc8, 0xd2, 0x78, 0x96, 0x7e, 0x5b, 0xfa, 0x4b, 0x89, 0x2c, 0xfd, - 0x36, 0xb2, 0x34, 0xb6, 0x05, 0xb5, 0x5d, 0x77, 0x7b, 0x43, 0x37, 0xb6, 0x95, 0x5b, 0x55, 0x99, - 0x2f, 0x84, 0x7c, 0x0b, 0xba, 0x9c, 0xcc, 0xc2, 0x34, 0x2d, 0x59, 0x87, 0x47, 0xde, 0xa0, 0x9e, - 0x2b, 0x47, 0x79, 0xd3, 0xa6, 0xb4, 0xa3, 0x60, 0x84, 0x0a, 0xc1, 0xbd, 0xb3, 0x3e, 0x97, 0x4d, - 0x82, 0xfd, 0xca, 0x72, 0x3f, 0x4f, 0xdd, 0x6b, 0xd1, 0x60, 0xd5, 0x73, 0x0d, 0xea, 0xfb, 0x96, - 0xd3, 0x52, 0xb0, 0x43, 0x11, 0xec, 0x5a, 0x36, 0x09, 0xf6, 0x2b, 0x4b, 0x5e, 0x86, 0x09, 0x91, - 0x25, 0x16, 0xdb, 0xd9, 0x1d, 0xdd, 0xb2, 0xf5, 0x0d, 0xcb, 0x56, 0xff, 0x05, 0x1b, 0x15, 0xe7, - 0x0a, 0x6b, 0x7d, 0x68, 0xb0, 0x6f, 0x69, 0x72, 0x15, 0xc6, 0xd5, 0xa9, 0xd2, 0x2a, 0xf5, 0x9a, - 0xe1, 0x39, 0xf8, 0x68, 0xe3, 0x02, 0xdb, 0xef, 0xcd, 0xd3, 0x8e, 0x47, 0x0d, 0xae, 0x75, 0xa5, - 0xa8, 0xb0, 0xa7, 0x1c, 0x41, 0x38, 0xc3, 0x0f, 0xbb, 0xd7, 0x3b, 0x73, 0xae, 0x6b, 0x9b, 0xee, - 0x2d, 0x47, 0x7d, 0xbb, 0x50, 0x6c, 0xf8, 0x41, 0x52, 0x33, 0x93, 0x02, 0xfb, 0x94, 0x64, 0x5f, - 0xce, 0x73, 0xe6, 0xdd, 0x5b, 0x4e, 0x1a, 0x15, 0xa2, 0x2f, 0x6f, 0xf6, 0xa1, 0xc1, 0xbe, 0xa5, - 0xc9, 0x02, 0x90, 0xf4, 0x17, 0xac, 0x77, 0xb8, 0x32, 0x34, 0xda, 0x38, 0x23, 0x82, 0x6b, 0xa4, - 0x73, 0x31, 0xa3, 0x04, 0x59, 0x86, 0xd3, 0xe9, 0x54, 0xc6, 0x8e, 0x7b, 0xd8, 0x8f, 0x8a, 0xb0, - 0x9a, 0x98, 0x91, 0x8f, 0x99, 0xa5, 0xb4, 0x3f, 0x2e, 0xc2, 0x68, 0xe2, 0x36, 0xf6, 0x03, 0x77, - 0xeb, 0x95, 0x69, 0xa0, 0x6d, 0xbf, 0xb5, 0x34, 0x7f, 0x85, 0xea, 0x26, 0xf5, 0xae, 0x51, 0x75, - 0x73, 0x9e, 0x4f, 0x2a, 0x2b, 0x89, 0x1c, 0x4c, 0x51, 0x92, 0x4d, 0xa8, 0x08, 0x7b, 0x6a, 0xde, - 0xff, 0x2c, 0x28, 0x19, 0x71, 0xa3, 0x2a, 0x5f, 0x72, 0x84, 0x49, 0x55, 0xc0, 0x6b, 0x01, 0x8c, - 0xc4, 0x29, 0xd8, 0x44, 0x12, 0x29, 0x6b, 0xc3, 0x09, 0x45, 0x6d, 0x09, 0x4a, 0x41, 0x30, 0xe8, - 0x7d, 0x5a, 0x61, 0x9f, 0x5f, 0x5b, 0x46, 0x86, 0xa1, 0x6d, 0xb2, 0xb6, 0xf3, 0x7d, 0xcb, 0x75, - 0x64, 0x70, 0xe5, 0x75, 0x18, 0x0e, 0xa4, 0x89, 0x6a, 0xb0, 0xfb, 0xc0, 0xdc, 0x5c, 0xac, 0xcc, - 0x53, 0x0a, 0x4b, 0xfb, 0x9b, 0x22, 0xd4, 0xc2, 0xed, 0xe4, 0x01, 0x82, 0x16, 0xbb, 0x50, 0x0b, - 0x9d, 0x75, 0x72, 0xff, 0x33, 0x2d, 0xf2, 0x21, 0xe1, 0x3b, 0xa0, 0xf0, 0x15, 0x23, 0x1e, 0x71, - 0x47, 0xa0, 0x52, 0x0e, 0x47, 0xa0, 0x0e, 0x0c, 0x07, 0x9e, 0xd5, 0x6a, 0x49, 0xdd, 0x36, 0x8f, - 0x27, 0x50, 0x28, 0xae, 0x35, 0x01, 0x28, 0x25, 0x2b, 0x5e, 0x50, 0xb1, 0xd1, 0x5e, 0x83, 0xf1, - 0x34, 0x25, 0x57, 0xfc, 0x8c, 0x2d, 0x6a, 0x76, 0x6d, 0x25, 0xe3, 0x48, 0xf1, 0x93, 0xe9, 0x18, - 0x52, 0xb0, 0xcd, 0x1f, 0x6b, 0xa6, 0x37, 0x5c, 0x47, 0x6d, 0xab, 0xb9, 0x0e, 0xbd, 0x26, 0xd3, - 0x30, 0xcc, 0xd5, 0xfe, 0xb1, 0x04, 0x67, 0x23, 0xa3, 0xc0, 0x8a, 0xee, 0xe8, 0xad, 0x03, 0xfc, - 0x28, 0xeb, 0xfd, 0x1b, 0x16, 0x87, 0x8d, 0x3c, 0x5f, 0x7a, 0x00, 0x22, 0xcf, 0xff, 0xb4, 0x00, - 0xdc, 0xb1, 0x90, 0x7c, 0x09, 0x46, 0xf4, 0xd8, 0x3f, 0x12, 0x65, 0x73, 0x5e, 0xce, 0xdd, 0x9c, - 0xdc, 0x7f, 0x31, 0x74, 0x94, 0x89, 0xa7, 0x62, 0x82, 0x21, 0x71, 0xa1, 0xba, 0xa9, 0xdb, 0x36, - 0xd3, 0x85, 0x72, 0x1f, 0x72, 0x24, 0x98, 0xf3, 0x6e, 0xbe, 0x20, 0xa1, 0x31, 0x64, 0xa2, 0xfd, - 0x43, 0x01, 0x46, 0x9b, 0xb6, 0x65, 0x5a, 0x4e, 0xeb, 0x18, 0x43, 0xce, 0xdf, 0x80, 0x8a, 0x6f, - 0x5b, 0x26, 0x1d, 0x70, 0x1e, 0x17, 0x2b, 0x08, 0x03, 0x40, 0x81, 0x93, 0x8c, 0x61, 0x5f, 0x3a, - 0x40, 0x0c, 0xfb, 0x9f, 0x0f, 0x81, 0x74, 0x4e, 0x25, 0x5d, 0xa8, 0xb5, 0x54, 0x68, 0x6c, 0xf9, - 0x8d, 0x57, 0x72, 0x84, 0x55, 0x4b, 0x04, 0xd9, 0x16, 0xb3, 0x6e, 0x98, 0x88, 0x11, 0x27, 0x42, - 0x93, 0xbf, 0xc5, 0x9c, 0xcf, 0xf9, 0x5b, 0x4c, 0xc1, 0xae, 0xf7, 0xc7, 0x98, 0x3a, 0x94, 0xb7, - 0x82, 0xa0, 0x23, 0xc7, 0xd5, 0xe0, 0xde, 0xc7, 0x51, 0x64, 0x0f, 0xa1, 0x8d, 0xb0, 0x77, 0xe4, - 0xd0, 0x8c, 0x85, 0xa3, 0x87, 0x7f, 0x63, 0x9a, 0xcb, 0x75, 0xd0, 0x1d, 0x67, 0xc1, 0xde, 0x91, - 0x43, 0x93, 0x2f, 0x42, 0x3d, 0xf0, 0x74, 0xc7, 0xdf, 0x74, 0xbd, 0x36, 0xf5, 0xe4, 0xee, 0x70, - 0x21, 0xc7, 0x9f, 0x21, 0xd7, 0x22, 0x34, 0x71, 0x82, 0x96, 0x48, 0xc2, 0x38, 0x37, 0xb2, 0x0d, - 0xd5, 0xae, 0x29, 0x2a, 0x26, 0xcd, 0x26, 0xb3, 0x79, 0x7e, 0xf6, 0x19, 0x3b, 0xc6, 0x56, 0x6f, - 0x18, 0x32, 0x48, 0xfe, 0x78, 0x6c, 0xf8, 0xa8, 0x7e, 0x3c, 0x16, 0xef, 0x8d, 0x59, 0x61, 0x07, - 0x48, 0x5b, 0x6a, 0x94, 0x4e, 0x4b, 0x7a, 0xe1, 0x2c, 0xe4, 0x56, 0xf6, 0x04, 0xcb, 0x7a, 0xa8, - 0x95, 0x3a, 0x2d, 0x54, 0x3c, 0xb4, 0x36, 0x48, 0xeb, 0x36, 0x31, 0x12, 0xbf, 0xe7, 0x10, 0x77, - 0x61, 0xa6, 0x0f, 0x36, 0x1f, 0x84, 0xff, 0x89, 0x88, 0x85, 0x07, 0xce, 0xfc, 0x0f, 0x87, 0xf6, - 0xb7, 0x45, 0x28, 0xad, 0x2d, 0x37, 0x45, 0xc8, 0x3f, 0xfe, 0xef, 0x1b, 0xda, 0xdc, 0xb6, 0x3a, - 0x37, 0xa9, 0x67, 0x6d, 0xee, 0xca, 0x4d, 0x6f, 0x2c, 0xe4, 0x5f, 0x9a, 0x02, 0x33, 0x4a, 0x91, - 0x57, 0x60, 0xc4, 0xd0, 0xe7, 0xa8, 0x17, 0x0c, 0xb2, 0xa5, 0xe7, 0x97, 0xfe, 0xe6, 0x66, 0xa3, - 0xe2, 0x98, 0x00, 0x23, 0xeb, 0x00, 0x46, 0x04, 0x5d, 0x3a, 0xb4, 0x21, 0x22, 0x06, 0x1c, 0x03, - 0x22, 0x08, 0xb5, 0x6d, 0x46, 0xca, 0x51, 0xcb, 0x87, 0x41, 0xe5, 0x3d, 0xe7, 0x9a, 0x2a, 0x8b, - 0x11, 0x8c, 0xe6, 0xc0, 0x68, 0xe2, 0x9f, 0x1d, 0xe4, 0x63, 0x50, 0x75, 0x3b, 0xb1, 0xe9, 0xb4, - 0xc6, 0xfd, 0xfd, 0xaa, 0x37, 0x64, 0xda, 0x9d, 0xbd, 0xc9, 0xd1, 0x65, 0xb7, 0x65, 0x19, 0x2a, - 0x01, 0x43, 0x72, 0xa2, 0xc1, 0x10, 0xbf, 0xa9, 0xa3, 0xfe, 0xd8, 0xc1, 0xd7, 0x0e, 0x1e, 0x54, - 0xdf, 0x47, 0x99, 0xa3, 0x7d, 0xb9, 0x0c, 0xd1, 0x99, 0x10, 0xf1, 0x61, 0x48, 0x78, 0x22, 0xcb, - 0x99, 0xfb, 0x58, 0x9d, 0x9e, 0x25, 0x2b, 0xd2, 0x82, 0xd2, 0x6b, 0xee, 0x46, 0xee, 0x89, 0x3b, - 0x76, 0x45, 0x57, 0x58, 0xa9, 0x62, 0x09, 0xc8, 0x38, 0x90, 0x5f, 0x2d, 0xc0, 0x49, 0x3f, 0xad, - 0x74, 0xca, 0xee, 0x80, 0xf9, 0xb5, 0xeb, 0xb4, 0x1a, 0x2b, 0x1d, 0x33, 0xfb, 0x65, 0x63, 0x6f, - 0x5d, 0x98, 0xfc, 0xc5, 0x61, 0x8d, 0xec, 0x4e, 0x8b, 0x39, 0xff, 0x33, 0x97, 0x94, 0x7f, 0x32, - 0x0d, 0x25, 0x2b, 0xed, 0xab, 0x45, 0xa8, 0xc7, 0x66, 0xeb, 0xdc, 0x3f, 0x82, 0xb9, 0x9d, 0xfa, - 0x11, 0xcc, 0xea, 0xe0, 0x67, 0x97, 0x51, 0xad, 0x8e, 0xfb, 0x5f, 0x30, 0xdf, 0x2f, 0x42, 0x69, - 0x7d, 0x7e, 0x21, 0xb9, 0x5d, 0x2c, 0xdc, 0x87, 0xed, 0xe2, 0x16, 0x0c, 0x6f, 0x74, 0x2d, 0x3b, - 0xb0, 0x9c, 0xdc, 0x41, 0x04, 0xd4, 0x7f, 0x73, 0xe4, 0x5d, 0x5c, 0x81, 0x8a, 0x0a, 0x9e, 0xb4, - 0x60, 0xb8, 0x25, 0xa2, 0xb8, 0xe5, 0xf6, 0xe8, 0x92, 0xd1, 0xe0, 0x04, 0x23, 0xf9, 0x82, 0x0a, - 0x5d, 0xdb, 0x05, 0xf9, 0xe7, 0xed, 0xfb, 0x2e, 0x4d, 0xed, 0x8b, 0x10, 0x6a, 0x01, 0xf7, 0x9f, - 0xf9, 0x3f, 0x17, 0x20, 0xa9, 0xf8, 0xdc, 0xff, 0xde, 0xb4, 0x9d, 0xee, 0x4d, 0xf3, 0x47, 0x31, - 0xf8, 0xb2, 0x3b, 0x94, 0xf6, 0x87, 0x45, 0x18, 0xba, 0x6f, 0x17, 0x3f, 0x69, 0xc2, 0x39, 0x6d, - 0x2e, 0xe7, 0xc4, 0xd8, 0xd7, 0x35, 0xad, 0x9d, 0x72, 0x4d, 0xcb, 0xfb, 0xa7, 0xcf, 0x7b, 0x38, - 0xa6, 0xfd, 0x65, 0x01, 0xe4, 0xb4, 0xbc, 0xe4, 0xf8, 0x81, 0xee, 0x18, 0xfc, 0x87, 0xf3, 0x72, - 0x0d, 0xc8, 0xeb, 0x01, 0x21, 0xbd, 0x84, 0xc4, 0xb2, 0xcf, 0x9f, 0xd5, 0x9c, 0x4f, 0x3e, 0x02, - 0xd5, 0x2d, 0xd7, 0x0f, 0xf8, 0x3c, 0x5f, 0x4c, 0xda, 0x75, 0xae, 0xc8, 0x74, 0x0c, 0x29, 0xd2, - 0x27, 0x85, 0x95, 0xfe, 0x27, 0x85, 0xda, 0xb7, 0x8b, 0x30, 0xf2, 0x5e, 0xb9, 0xbd, 0x9a, 0xe5, - 0xca, 0x57, 0xca, 0xe9, 0xca, 0x57, 0x3e, 0x8c, 0x2b, 0x9f, 0xf6, 0x83, 0x02, 0xc0, 0x7d, 0xbb, - 0x3a, 0x6b, 0x26, 0xbd, 0xec, 0x72, 0xf7, 0xab, 0x6c, 0x1f, 0xbb, 0xdf, 0xab, 0xa8, 0x4f, 0xe2, - 0x1e, 0x76, 0x6f, 0x16, 0x60, 0x4c, 0x4f, 0x78, 0xad, 0xe5, 0x56, 0x2d, 0x53, 0x4e, 0x70, 0xe1, - 0x35, 0xc1, 0x64, 0x3a, 0xa6, 0xd8, 0x92, 0xe7, 0xa3, 0xb0, 0xad, 0xd7, 0xa3, 0x6e, 0xdf, 0x13, - 0x6f, 0x95, 0xab, 0x39, 0x09, 0xca, 0x7b, 0x78, 0x09, 0x96, 0x8e, 0xc4, 0x4b, 0x30, 0x7e, 0xff, - 0xa9, 0x7c, 0xd7, 0xfb, 0x4f, 0x3b, 0x50, 0xdb, 0xf4, 0xdc, 0x36, 0x77, 0xc4, 0x93, 0xff, 0x08, - 0xbd, 0x9c, 0x63, 0x4d, 0x89, 0xfe, 0x8e, 0x1d, 0xd9, 0x78, 0x16, 0x14, 0x3e, 0x46, 0xac, 0xb8, - 0x41, 0xda, 0x15, 0x5c, 0x87, 0x8e, 0x92, 0x6b, 0x38, 0x97, 0xac, 0x09, 0x74, 0x54, 0x6c, 0x92, - 0xce, 0x77, 0xc3, 0xf7, 0xc7, 0xf9, 0x4e, 0xfb, 0x7e, 0x59, 0x4d, 0x60, 0x0f, 0x5c, 0x84, 0xc0, - 0xf7, 0xfe, 0x95, 0xcb, 0xf4, 0x7d, 0xc8, 0xe1, 0xfb, 0x78, 0x1f, 0xb2, 0x7a, 0x34, 0xf7, 0x21, - 0x6b, 0x87, 0xb8, 0x0f, 0xb9, 0x57, 0x82, 0xd4, 0xa6, 0xeb, 0xfd, 0xa3, 0x8d, 0xff, 0x50, 0x47, - 0x1b, 0x6f, 0x15, 0x21, 0x9a, 0x45, 0x0e, 0xe9, 0xfa, 0xf1, 0x32, 0x54, 0xdb, 0xfa, 0xed, 0x79, - 0x6a, 0xeb, 0xbb, 0x79, 0xfe, 0x0a, 0xb9, 0x22, 0x31, 0x30, 0x44, 0x23, 0x3e, 0x80, 0x15, 0x46, - 0x66, 0xce, 0x6d, 0xaa, 0x8e, 0x82, 0x3c, 0x0b, 0x63, 0x58, 0xf4, 0x8e, 0x31, 0x36, 0xda, 0x5f, - 0x14, 0x41, 0x86, 0xf0, 0x26, 0x14, 0x2a, 0x9b, 0xd6, 0x6d, 0x6a, 0xe6, 0x76, 0x83, 0x8c, 0xfd, - 0xab, 0x57, 0xd8, 0xe2, 0x79, 0x02, 0x0a, 0x74, 0x6e, 0x64, 0x15, 0x67, 0x2b, 0x52, 0x7e, 0x39, - 0x8c, 0xac, 0xf1, 0x33, 0x1a, 0x69, 0x64, 0x15, 0x49, 0xa8, 0x78, 0x08, 0x9b, 0x2e, 0x3f, 0xe0, - 0x96, 0x22, 0xcd, 0x63, 0xd3, 0x8d, 0x1d, 0x94, 0x2b, 0x9b, 0xae, 0x2f, 0x2e, 0x44, 0x4b, 0x1e, - 0x8d, 0xcf, 0x7f, 0xef, 0x87, 0x17, 0x1e, 0xfa, 0xc1, 0x0f, 0x2f, 0x3c, 0xf4, 0xce, 0x0f, 0x2f, - 0x3c, 0xf4, 0xe5, 0xfd, 0x0b, 0x85, 0xef, 0xed, 0x5f, 0x28, 0xfc, 0x60, 0xff, 0x42, 0xe1, 0x9d, - 0xfd, 0x0b, 0x85, 0xbf, 0xdb, 0xbf, 0x50, 0xf8, 0xa5, 0xbf, 0xbf, 0xf0, 0xd0, 0xe7, 0x9e, 0x8b, - 0xaa, 0x30, 0xad, 0xaa, 0x30, 0xad, 0x18, 0x4e, 0x77, 0xb6, 0x5b, 0xd3, 0xac, 0x0a, 0x51, 0x8a, - 0xaa, 0xc2, 0xbf, 0x07, 0x00, 0x00, 0xff, 0xff, 0xf1, 0x80, 0x4f, 0xc1, 0x9f, 0x93, 0x00, 0x00, + // 7611 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5d, 0x6c, 0x24, 0xd7, + 0x75, 0xa6, 0xfa, 0x8f, 0xec, 0x3e, 0x4d, 0x72, 0x38, 0x77, 0x46, 0x23, 0xce, 0x68, 0x34, 0x1c, + 0x97, 0x2c, 0x79, 0xbc, 0xb6, 0xc9, 0x15, 0x57, 0x7f, 0xfe, 0x95, 0xd8, 0xe4, 0x90, 0xc3, 0x19, + 0x72, 0x86, 0x3e, 0x4d, 0x8e, 0x64, 0x6b, 0x6d, 0x6d, 0xb1, 0xea, 0xb2, 0x59, 0x62, 0x75, 0x55, + 0xab, 0xaa, 0x9a, 0x33, 0x94, 0x77, 0xe1, 0x1f, 0x2d, 0x20, 0x2d, 0x16, 0x8b, 0x5d, 0xf8, 0xc9, + 0xc0, 0xc2, 0xbb, 0xd8, 0xc5, 0x02, 0x7e, 0x30, 0xbc, 0x0f, 0x8b, 0xd5, 0x3e, 0x2c, 0x90, 0x38, + 0x0e, 0x82, 0xc4, 0x0e, 0xf2, 0xe3, 0x87, 0x00, 0x51, 0x5e, 0x88, 0x98, 0x41, 0x1e, 0x12, 0x20, + 0x86, 0x11, 0x03, 0x89, 0x3d, 0x30, 0xe2, 0xe0, 0xfe, 0xd5, 0x5f, 0x57, 0xcf, 0x90, 0x5d, 0xe4, + 0x68, 0x94, 0xe8, 0xad, 0xea, 0xdc, 0x73, 0xbf, 0x73, 0xef, 0xa9, 0xfb, 0x73, 0xee, 0xb9, 0xe7, + 0xde, 0x82, 0xc5, 0x96, 0x15, 0x6c, 0x75, 0x37, 0xa6, 0x0c, 0xb7, 0x3d, 0xed, 0x74, 0xdb, 0x7a, + 0xc7, 0x73, 0x5f, 0xe3, 0x0f, 0x9b, 0xb6, 0x7b, 0x6b, 0xba, 0xb3, 0xdd, 0x9a, 0xd6, 0x3b, 0x96, + 0x1f, 0x51, 0x76, 0x9e, 0xd2, 0xed, 0xce, 0x96, 0xfe, 0xd4, 0x74, 0x8b, 0x3a, 0xd4, 0xd3, 0x03, + 0x6a, 0x4e, 0x75, 0x3c, 0x37, 0x70, 0xc9, 0x73, 0x11, 0xd0, 0x94, 0x02, 0x9a, 0x52, 0xd9, 0xa6, + 0x3a, 0xdb, 0xad, 0x29, 0x06, 0x14, 0x51, 0x14, 0xd0, 0xb9, 0x4f, 0xc4, 0x4a, 0xd0, 0x72, 0x5b, + 0xee, 0x34, 0xc7, 0xdb, 0xe8, 0x6e, 0xf2, 0x37, 0xfe, 0xc2, 0x9f, 0x84, 0x9c, 0x73, 0xda, 0xf6, + 0xf3, 0xfe, 0x94, 0xe5, 0xb2, 0x62, 0x4d, 0x1b, 0xae, 0x47, 0xa7, 0x77, 0x7a, 0xca, 0x72, 0xee, + 0xe9, 0x88, 0xa7, 0xad, 0x1b, 0x5b, 0x96, 0x43, 0xbd, 0x5d, 0x55, 0x97, 0x69, 0x8f, 0xfa, 0x6e, + 0xd7, 0x33, 0xe8, 0xa1, 0x72, 0xf9, 0xd3, 0x6d, 0x1a, 0xe8, 0x59, 0xb2, 0xa6, 0xfb, 0xe5, 0xf2, + 0xba, 0x4e, 0x60, 0xb5, 0x7b, 0xc5, 0x3c, 0x7b, 0xaf, 0x0c, 0xbe, 0xb1, 0x45, 0xdb, 0x7a, 0x3a, + 0x9f, 0xf6, 0x03, 0x80, 0x53, 0xb3, 0x1b, 0x7e, 0xe0, 0xe9, 0x46, 0xb0, 0xea, 0x9a, 0x6b, 0xb4, + 0xdd, 0xb1, 0xf5, 0x80, 0x92, 0x6d, 0xa8, 0xb2, 0xb2, 0x99, 0x7a, 0xa0, 0x4f, 0x14, 0x2e, 0x16, + 0x2e, 0xd5, 0x67, 0x66, 0xa7, 0x06, 0xfc, 0x16, 0x53, 0x2b, 0x12, 0xa8, 0x31, 0xb2, 0xbf, 0x37, + 0x59, 0x55, 0x6f, 0x18, 0x0a, 0x20, 0xdf, 0x2a, 0xc0, 0x88, 0xe3, 0x9a, 0xb4, 0x49, 0x6d, 0x6a, + 0x04, 0xae, 0x37, 0x51, 0xbc, 0x58, 0xba, 0x54, 0x9f, 0xf9, 0xf2, 0xc0, 0x12, 0x33, 0x6a, 0x34, + 0x75, 0x3d, 0x26, 0xe0, 0xb2, 0x13, 0x78, 0xbb, 0x8d, 0xd3, 0x3f, 0xdc, 0x9b, 0x7c, 0x68, 0x7f, + 0x6f, 0x72, 0x24, 0x9e, 0x84, 0x89, 0x92, 0x90, 0x75, 0xa8, 0x07, 0xae, 0xcd, 0x54, 0x66, 0xb9, + 0x8e, 0x3f, 0x51, 0xe2, 0x05, 0xbb, 0x30, 0x25, 0xb4, 0xcd, 0xc4, 0x4f, 0xb1, 0xe6, 0x32, 0xb5, + 0xf3, 0xd4, 0xd4, 0x5a, 0xc8, 0xd6, 0x38, 0x25, 0x81, 0xeb, 0x11, 0xcd, 0xc7, 0x38, 0x0e, 0xa1, + 0x70, 0xc2, 0xa7, 0x46, 0xd7, 0xb3, 0x82, 0xdd, 0x39, 0xd7, 0x09, 0xe8, 0xed, 0x60, 0xa2, 0xcc, + 0xb5, 0xfc, 0x64, 0x16, 0xf4, 0xaa, 0x6b, 0x36, 0x93, 0xdc, 0x8d, 0x53, 0xfb, 0x7b, 0x93, 0x27, + 0x52, 0x44, 0x4c, 0x63, 0x12, 0x07, 0xc6, 0xad, 0xb6, 0xde, 0xa2, 0xab, 0x5d, 0xdb, 0x6e, 0x52, + 0xc3, 0xa3, 0x81, 0x3f, 0x51, 0xe1, 0x55, 0xb8, 0x94, 0x25, 0x67, 0xd9, 0x35, 0x74, 0xfb, 0xc6, + 0xc6, 0x6b, 0xd4, 0x08, 0x90, 0x6e, 0x52, 0x8f, 0x3a, 0x06, 0x6d, 0x4c, 0xc8, 0xca, 0x8c, 0x2f, + 0xa5, 0x90, 0xb0, 0x07, 0x9b, 0x2c, 0xc2, 0xc9, 0x8e, 0x67, 0xb9, 0xbc, 0x08, 0xb6, 0xee, 0xfb, + 0xd7, 0xf5, 0x36, 0x9d, 0x18, 0xba, 0x58, 0xb8, 0x54, 0x6b, 0x9c, 0x95, 0x30, 0x27, 0x57, 0xd3, + 0x0c, 0xd8, 0x9b, 0x87, 0x5c, 0x82, 0xaa, 0x22, 0x4e, 0x0c, 0x5f, 0x2c, 0x5c, 0xaa, 0x88, 0xb6, + 0xa3, 0xf2, 0x62, 0x98, 0x4a, 0x16, 0xa0, 0xaa, 0x6f, 0x6e, 0x5a, 0x0e, 0xe3, 0xac, 0x72, 0x15, + 0x9e, 0xcf, 0xaa, 0xda, 0xac, 0xe4, 0x11, 0x38, 0xea, 0x0d, 0xc3, 0xbc, 0xe4, 0x2a, 0x10, 0x9f, + 0x7a, 0x3b, 0x96, 0x41, 0x67, 0x0d, 0xc3, 0xed, 0x3a, 0x01, 0x2f, 0x7b, 0x8d, 0x97, 0xfd, 0x9c, + 0x2c, 0x3b, 0x69, 0xf6, 0x70, 0x60, 0x46, 0x2e, 0xf2, 0x22, 0x8c, 0xcb, 0x6e, 0x17, 0x69, 0x01, + 0x38, 0xd2, 0x69, 0xa6, 0x48, 0x4c, 0xa5, 0x61, 0x0f, 0x37, 0x31, 0xe1, 0xbc, 0xde, 0x0d, 0xdc, + 0x36, 0x83, 0x4c, 0x0a, 0x5d, 0x73, 0xb7, 0xa9, 0x33, 0x51, 0xbf, 0x58, 0xb8, 0x54, 0x6d, 0x5c, + 0xdc, 0xdf, 0x9b, 0x3c, 0x3f, 0x7b, 0x17, 0x3e, 0xbc, 0x2b, 0x0a, 0xb9, 0x01, 0x35, 0xd3, 0xf1, + 0x57, 0x5d, 0xdb, 0x32, 0x76, 0x27, 0x46, 0x78, 0x01, 0x9f, 0x92, 0x55, 0xad, 0xcd, 0x5f, 0x6f, + 0x8a, 0x84, 0x3b, 0x7b, 0x93, 0xe7, 0x7b, 0x47, 0xc7, 0xa9, 0x30, 0x1d, 0x23, 0x0c, 0xb2, 0xc2, + 0x01, 0xe7, 0x5c, 0x67, 0xd3, 0x6a, 0x4d, 0x8c, 0xf2, 0xaf, 0x71, 0xb1, 0x4f, 0x83, 0x9e, 0xbf, + 0xde, 0x14, 0x7c, 0x8d, 0x51, 0x29, 0x4e, 0xbc, 0x62, 0x84, 0x40, 0x4c, 0x18, 0x53, 0xe3, 0xea, + 0x9c, 0xad, 0x5b, 0x6d, 0x7f, 0x62, 0x8c, 0x37, 0xde, 0x0f, 0xf7, 0xc1, 0xc4, 0x38, 0x73, 0xe3, + 0x8c, 0xac, 0xca, 0x58, 0x82, 0xec, 0x63, 0x0a, 0xf3, 0xdc, 0x0b, 0x70, 0xb2, 0x67, 0x6c, 0x20, + 0xe3, 0x50, 0xda, 0xa6, 0xbb, 0x7c, 0xe8, 0xab, 0x21, 0x7b, 0x24, 0xa7, 0xa1, 0xb2, 0xa3, 0xdb, + 0x5d, 0x3a, 0x51, 0xe4, 0x34, 0xf1, 0xf2, 0xa9, 0xe2, 0xf3, 0x05, 0xed, 0x7f, 0x96, 0x60, 0x44, + 0x8d, 0x38, 0x4d, 0xcb, 0xd9, 0x26, 0x2f, 0x41, 0xc9, 0x76, 0x5b, 0x72, 0xdc, 0xfc, 0xcc, 0xc0, + 0xa3, 0xd8, 0xb2, 0xdb, 0x6a, 0x0c, 0xef, 0xef, 0x4d, 0x96, 0x96, 0xdd, 0x16, 0x32, 0x44, 0x62, + 0x40, 0x65, 0x5b, 0xdf, 0xdc, 0xd6, 0x79, 0x19, 0xea, 0x33, 0x8d, 0x81, 0xa1, 0xaf, 0x31, 0x14, + 0x56, 0xd6, 0x46, 0x6d, 0x7f, 0x6f, 0xb2, 0xc2, 0x5f, 0x51, 0x60, 0x13, 0x17, 0x6a, 0x1b, 0xb6, + 0x6e, 0x6c, 0x6f, 0xb9, 0x36, 0x9d, 0x28, 0xe5, 0x14, 0xd4, 0x50, 0x48, 0xe2, 0x33, 0x87, 0xaf, + 0x18, 0xc9, 0x20, 0x06, 0x0c, 0x75, 0x4d, 0xdf, 0x72, 0xb6, 0xe5, 0x18, 0xf8, 0xc2, 0xc0, 0xd2, + 0xd6, 0xe7, 0x79, 0x9d, 0x60, 0x7f, 0x6f, 0x72, 0x48, 0x3c, 0xa3, 0x84, 0xd6, 0x7e, 0x5a, 0x87, + 0x31, 0xf5, 0x91, 0x6e, 0x52, 0x2f, 0xa0, 0xb7, 0xc9, 0x45, 0x28, 0x3b, 0xac, 0x6b, 0xf2, 0x8f, + 0xdc, 0x18, 0x91, 0xcd, 0xa5, 0xcc, 0xbb, 0x24, 0x4f, 0x61, 0x25, 0x13, 0x4d, 0x45, 0x2a, 0x7c, + 0xf0, 0x92, 0x35, 0x39, 0x8c, 0x28, 0x99, 0x78, 0x46, 0x09, 0x4d, 0x5e, 0x81, 0x32, 0xaf, 0xbc, + 0x50, 0xf5, 0x67, 0x07, 0x17, 0xc1, 0xaa, 0x5e, 0x65, 0x35, 0xe0, 0x15, 0xe7, 0xa0, 0xac, 0x29, + 0x76, 0xcd, 0x4d, 0xa9, 0xd8, 0xcf, 0xe4, 0x50, 0xec, 0x82, 0x68, 0x8a, 0xeb, 0xf3, 0x0b, 0xc8, + 0x10, 0xc9, 0x7f, 0x2e, 0xc0, 0x49, 0xc3, 0x75, 0x02, 0x9d, 0x99, 0x1a, 0x6a, 0x92, 0x9d, 0xa8, + 0x70, 0x39, 0x57, 0x07, 0x96, 0x33, 0x97, 0x46, 0x6c, 0x3c, 0xcc, 0xe6, 0x8c, 0x1e, 0x32, 0xf6, + 0xca, 0x26, 0xff, 0xb5, 0x00, 0x0f, 0xb3, 0xb1, 0xbc, 0x87, 0x99, 0xcf, 0x40, 0x47, 0x5b, 0xaa, + 0xb3, 0xfb, 0x7b, 0x93, 0x0f, 0x2f, 0x65, 0x09, 0xc3, 0xec, 0x32, 0xb0, 0xd2, 0x9d, 0xd2, 0x7b, + 0xcd, 0x12, 0x3e, 0xbb, 0xd5, 0x67, 0x96, 0x8f, 0xd2, 0xd4, 0x69, 0x3c, 0x2a, 0x9b, 0x72, 0x96, + 0x65, 0x87, 0x59, 0xa5, 0x20, 0x97, 0x61, 0x78, 0xc7, 0xb5, 0xbb, 0x6d, 0xea, 0x4f, 0x54, 0xf9, + 0x10, 0x7b, 0x2e, 0x6b, 0x88, 0xbd, 0xc9, 0x59, 0x1a, 0x27, 0x24, 0xfc, 0xb0, 0x78, 0xf7, 0x51, + 0xe5, 0x25, 0x16, 0x0c, 0xd9, 0x56, 0xdb, 0x0a, 0x7c, 0x3e, 0x71, 0xd6, 0x67, 0x2e, 0x0f, 0x5c, + 0x2d, 0xd1, 0x45, 0x97, 0x39, 0x98, 0xe8, 0x35, 0xe2, 0x19, 0xa5, 0x00, 0x36, 0x14, 0xfa, 0x86, + 0x6e, 0x8b, 0x89, 0xb5, 0x3e, 0xf3, 0xb9, 0xc1, 0xbb, 0x0d, 0x43, 0x69, 0x8c, 0xca, 0x3a, 0x55, + 0xf8, 0x2b, 0x0a, 0x6c, 0xf2, 0x25, 0x18, 0x4b, 0x7c, 0x4d, 0x7f, 0xa2, 0xce, 0xb5, 0xf3, 0x58, + 0x96, 0x76, 0x42, 0xae, 0x68, 0xe6, 0x49, 0xb4, 0x10, 0x1f, 0x53, 0x60, 0xe4, 0x1a, 0x54, 0x7d, + 0xcb, 0xa4, 0x86, 0xee, 0xf9, 0x13, 0x23, 0x07, 0x01, 0x1e, 0x97, 0xc0, 0xd5, 0xa6, 0xcc, 0x86, + 0x21, 0x00, 0x99, 0x02, 0xe8, 0xe8, 0x5e, 0x60, 0x09, 0x43, 0x75, 0x94, 0x1b, 0x4d, 0x63, 0xfb, + 0x7b, 0x93, 0xb0, 0x1a, 0x52, 0x31, 0xc6, 0xc1, 0xf8, 0x59, 0xde, 0x25, 0xa7, 0xd3, 0x0d, 0xc4, + 0xc4, 0x5a, 0x13, 0xfc, 0xcd, 0x90, 0x8a, 0x31, 0x0e, 0xf2, 0xbd, 0x02, 0x3c, 0x1a, 0xbd, 0xf6, + 0x76, 0xb2, 0x13, 0x47, 0xde, 0xc9, 0x26, 0xf7, 0xf7, 0x26, 0x1f, 0x6d, 0xf6, 0x17, 0x89, 0x77, + 0x2b, 0x8f, 0xf6, 0x12, 0x8c, 0xce, 0x76, 0x83, 0x2d, 0xd7, 0xb3, 0xde, 0xe0, 0x46, 0x37, 0x59, + 0x80, 0x4a, 0xc0, 0x8d, 0x27, 0x31, 0x2f, 0x3f, 0x91, 0xa5, 0x6a, 0x61, 0xc8, 0x5e, 0xa3, 0xbb, + 0xca, 0x1a, 0x10, 0xf3, 0xa3, 0x30, 0xa6, 0x44, 0x76, 0xed, 0xdf, 0x17, 0x60, 0xb8, 0xa1, 0x1b, + 0xdb, 0xee, 0xe6, 0x26, 0x79, 0x19, 0xaa, 0x96, 0x13, 0x50, 0x6f, 0x47, 0xb7, 0x25, 0xec, 0x54, + 0x0c, 0x36, 0x5c, 0x89, 0x45, 0xf5, 0x66, 0x6b, 0x1e, 0x26, 0x68, 0xbe, 0x2b, 0xd7, 0x0a, 0xdc, + 0x1e, 0x5d, 0x92, 0x18, 0x18, 0xa2, 0x91, 0x49, 0xa8, 0xf8, 0x01, 0xed, 0xf8, 0x7c, 0xe6, 0x19, + 0x15, 0xc5, 0x68, 0x32, 0x02, 0x0a, 0xba, 0xf6, 0x3f, 0x0a, 0x50, 0x6b, 0xe8, 0xbe, 0x65, 0xb0, + 0x5a, 0x92, 0x39, 0x28, 0x77, 0x7d, 0xea, 0x1d, 0xae, 0x6e, 0x7c, 0xb2, 0x58, 0xf7, 0xa9, 0x87, + 0x3c, 0x33, 0xb9, 0x01, 0xd5, 0x8e, 0xee, 0xfb, 0xb7, 0x5c, 0xcf, 0x94, 0x13, 0xde, 0x01, 0x81, + 0x84, 0x71, 0x2e, 0xb3, 0x62, 0x08, 0xa2, 0xd5, 0x21, 0x9a, 0xf1, 0xb5, 0x9f, 0x17, 0xe0, 0x54, + 0xa3, 0xbb, 0xb9, 0x49, 0x3d, 0x69, 0x8b, 0x4a, 0x2b, 0x8f, 0x42, 0xc5, 0xa3, 0xa6, 0xe5, 0xcb, + 0xb2, 0xcf, 0x0f, 0xdc, 0x82, 0x90, 0xa1, 0x48, 0xa3, 0x92, 0xeb, 0x8b, 0x13, 0x50, 0xa0, 0x93, + 0x2e, 0xd4, 0x5e, 0xa3, 0x81, 0x1f, 0x78, 0x54, 0x6f, 0xcb, 0xda, 0x5d, 0x19, 0x58, 0xd4, 0x55, + 0x1a, 0x34, 0x39, 0x52, 0xdc, 0x86, 0x0d, 0x89, 0x18, 0x49, 0xd2, 0x7e, 0x50, 0x81, 0x91, 0x39, + 0xb7, 0xbd, 0x61, 0x39, 0xd4, 0xbc, 0x6c, 0xb6, 0x28, 0x79, 0x15, 0xca, 0xd4, 0x6c, 0x51, 0x59, + 0xdb, 0xc1, 0xa7, 0x7b, 0x06, 0x16, 0x19, 0x2d, 0xec, 0x0d, 0x39, 0x30, 0x59, 0x86, 0xb1, 0x4d, + 0xcf, 0x6d, 0x8b, 0x11, 0x74, 0x6d, 0xb7, 0x23, 0x2d, 0xd6, 0xc6, 0x87, 0xd5, 0xa8, 0xb4, 0x90, + 0x48, 0xbd, 0xb3, 0x37, 0x09, 0xd1, 0x1b, 0xa6, 0xf2, 0x92, 0x97, 0x61, 0x22, 0xa2, 0x84, 0x43, + 0xc9, 0x1c, 0x5b, 0x44, 0x70, 0x8b, 0xa5, 0xd2, 0x38, 0xbf, 0xbf, 0x37, 0x39, 0xb1, 0xd0, 0x87, + 0x07, 0xfb, 0xe6, 0x26, 0x6f, 0x15, 0x60, 0x3c, 0x4a, 0x14, 0xc3, 0xbb, 0x34, 0x54, 0x8e, 0x68, + 0xde, 0xe0, 0xab, 0xad, 0x85, 0x94, 0x08, 0xec, 0x11, 0x4a, 0x16, 0x60, 0x24, 0x70, 0x63, 0xfa, + 0xaa, 0x70, 0x7d, 0x69, 0xca, 0x3d, 0xb0, 0xe6, 0xf6, 0xd5, 0x56, 0x22, 0x1f, 0x41, 0x38, 0xa3, + 0xde, 0x53, 0x9a, 0x1a, 0xe2, 0x9a, 0x3a, 0xb7, 0xbf, 0x37, 0x79, 0x66, 0x2d, 0x93, 0x03, 0xfb, + 0xe4, 0x24, 0x5f, 0x2f, 0xc0, 0x98, 0x4a, 0x92, 0x3a, 0x1a, 0x3e, 0x4a, 0x1d, 0x11, 0xd6, 0x22, + 0xd6, 0x12, 0x02, 0x30, 0x25, 0x50, 0xfb, 0x45, 0x19, 0x6a, 0xe1, 0x00, 0x4b, 0x1e, 0x87, 0x0a, + 0x5f, 0xf8, 0x4b, 0xbb, 0x39, 0x9c, 0x39, 0xb9, 0x7f, 0x00, 0x45, 0x1a, 0x79, 0x02, 0x86, 0x0d, + 0xb7, 0xdd, 0xd6, 0x1d, 0x93, 0x3b, 0x73, 0x6a, 0x8d, 0x3a, 0x33, 0x18, 0xe6, 0x04, 0x09, 0x55, + 0x1a, 0x39, 0x0f, 0x65, 0xdd, 0x6b, 0x09, 0xbf, 0x4a, 0x4d, 0x8c, 0x47, 0xb3, 0x5e, 0xcb, 0x47, + 0x4e, 0x25, 0x9f, 0x84, 0x12, 0x75, 0x76, 0x26, 0xca, 0xfd, 0x2d, 0x92, 0xcb, 0xce, 0xce, 0x4d, + 0xdd, 0x6b, 0xd4, 0x65, 0x19, 0x4a, 0x97, 0x9d, 0x1d, 0x64, 0x79, 0xc8, 0x32, 0x0c, 0x53, 0x67, + 0x87, 0x7d, 0x7b, 0xe9, 0xf0, 0xf8, 0x50, 0x9f, 0xec, 0x8c, 0x45, 0x1a, 0xe7, 0xa1, 0x5d, 0x23, + 0xc9, 0xa8, 0x20, 0xc8, 0x17, 0x60, 0x44, 0x98, 0x38, 0x2b, 0xec, 0x9b, 0xf8, 0x13, 0x43, 0x1c, + 0x72, 0xb2, 0xbf, 0x8d, 0xc4, 0xf9, 0x22, 0x07, 0x53, 0x8c, 0xe8, 0x63, 0x02, 0x8a, 0x7c, 0x01, + 0x6a, 0x6a, 0x3d, 0xaa, 0xbe, 0x6c, 0xa6, 0x6f, 0x46, 0x2d, 0x62, 0x91, 0xbe, 0xde, 0xb5, 0x3c, + 0xda, 0xa6, 0x4e, 0xe0, 0x37, 0x4e, 0xaa, 0xd5, 0xba, 0x4a, 0xf5, 0x31, 0x42, 0x23, 0x1b, 0xbd, + 0x4e, 0x26, 0xe1, 0x21, 0x79, 0xbc, 0xcf, 0xa8, 0x3e, 0x80, 0x87, 0xe9, 0xcb, 0x70, 0x22, 0xf4, + 0x02, 0x49, 0x47, 0x82, 0xf0, 0x99, 0x3c, 0xcd, 0xb2, 0x2f, 0x25, 0x93, 0xee, 0xec, 0x4d, 0x3e, + 0x96, 0xe1, 0x4a, 0x88, 0x18, 0x30, 0x0d, 0xa6, 0x7d, 0xbf, 0x04, 0xbd, 0xd6, 0x7f, 0x52, 0x69, + 0x85, 0xa3, 0x56, 0x5a, 0xba, 0x42, 0x62, 0xf8, 0x7c, 0x5e, 0x66, 0xcb, 0x5f, 0xa9, 0xac, 0x0f, + 0x53, 0x3a, 0xea, 0x0f, 0xf3, 0xa0, 0xf4, 0x1d, 0xed, 0xed, 0x32, 0x8c, 0xcd, 0xeb, 0xb4, 0xed, + 0x3a, 0xf7, 0x5c, 0x0b, 0x15, 0x1e, 0x88, 0xb5, 0xd0, 0x25, 0xa8, 0x7a, 0xb4, 0x63, 0x5b, 0x86, + 0x2e, 0x8c, 0x2f, 0xe9, 0x7b, 0x44, 0x49, 0xc3, 0x30, 0xb5, 0xcf, 0x1a, 0xb8, 0xf4, 0x40, 0xae, + 0x81, 0xcb, 0xef, 0xfd, 0x1a, 0x58, 0xfb, 0x7a, 0x11, 0xb8, 0xa1, 0x42, 0x2e, 0x42, 0x99, 0x4d, + 0xc2, 0x69, 0xcf, 0x0b, 0x6f, 0x38, 0x3c, 0x85, 0x9c, 0x83, 0x62, 0xe0, 0xca, 0x9e, 0x07, 0x32, + 0xbd, 0xb8, 0xe6, 0x62, 0x31, 0x70, 0xc9, 0x1b, 0x00, 0x86, 0xeb, 0x98, 0x96, 0x72, 0xc9, 0xe7, + 0xab, 0xd8, 0x82, 0xeb, 0xdd, 0xd2, 0x3d, 0x73, 0x2e, 0x44, 0x14, 0xab, 0xa0, 0xe8, 0x1d, 0x63, + 0xd2, 0xc8, 0x0b, 0x30, 0xe4, 0x3a, 0x0b, 0x5d, 0xdb, 0xe6, 0x0a, 0xad, 0x35, 0x3e, 0xc2, 0x96, + 0xa6, 0x37, 0x38, 0xe5, 0xce, 0xde, 0xe4, 0x59, 0x61, 0xdf, 0xb2, 0xb7, 0x97, 0x3c, 0x2b, 0xb0, + 0x9c, 0x56, 0x33, 0xf0, 0xf4, 0x80, 0xb6, 0x76, 0x51, 0x66, 0xd3, 0xbe, 0x59, 0x80, 0xfa, 0x82, + 0x75, 0x9b, 0x9a, 0x2f, 0x59, 0x8e, 0xe9, 0xde, 0x22, 0x08, 0x43, 0x36, 0x75, 0x5a, 0xc1, 0xd6, + 0x80, 0xeb, 0x07, 0xb1, 0x36, 0xe6, 0x08, 0x28, 0x91, 0xc8, 0x34, 0xd4, 0x84, 0xf5, 0x69, 0x39, + 0x2d, 0xae, 0xc3, 0x6a, 0x34, 0xe8, 0x35, 0x55, 0x02, 0x46, 0x3c, 0xda, 0x2e, 0x9c, 0xec, 0x51, + 0x03, 0x31, 0xa1, 0x1c, 0xe8, 0x2d, 0x35, 0xbe, 0x2e, 0x0c, 0xac, 0xe0, 0x35, 0xbd, 0x15, 0x53, + 0x2e, 0x9f, 0xe3, 0xd7, 0x74, 0x36, 0xc7, 0x33, 0x74, 0xed, 0x57, 0x05, 0xa8, 0x2e, 0x74, 0x1d, + 0x83, 0x2f, 0xd1, 0xee, 0xed, 0x91, 0x53, 0x06, 0x43, 0x31, 0xd3, 0x60, 0xe8, 0xc2, 0xd0, 0xf6, + 0xad, 0xd0, 0xa0, 0xa8, 0xcf, 0xac, 0x0c, 0xde, 0x2a, 0x64, 0x91, 0xa6, 0xae, 0x71, 0x3c, 0xb1, + 0x61, 0x34, 0x26, 0x0b, 0x34, 0x74, 0xed, 0x25, 0x2e, 0x54, 0x0a, 0x3b, 0xf7, 0x49, 0xa8, 0xc7, + 0xd8, 0x0e, 0xe5, 0x3b, 0xfe, 0x7f, 0x65, 0x18, 0x5a, 0x6c, 0x36, 0x67, 0x57, 0x97, 0xc8, 0x33, + 0x50, 0x97, 0x7b, 0x09, 0xd7, 0x23, 0x1d, 0x84, 0x5b, 0x49, 0xcd, 0x28, 0x09, 0xe3, 0x7c, 0xcc, + 0x1c, 0xf3, 0xa8, 0x6e, 0xb7, 0x65, 0x67, 0x09, 0xcd, 0x31, 0x64, 0x44, 0x14, 0x69, 0x44, 0x87, + 0x31, 0xb6, 0xc2, 0x63, 0x2a, 0x14, 0xab, 0x37, 0xd9, 0x6d, 0x0e, 0xb8, 0xbe, 0xe3, 0x46, 0xe2, + 0x7a, 0x02, 0x00, 0x53, 0x80, 0xe4, 0x79, 0xa8, 0xea, 0xdd, 0x60, 0x8b, 0x1b, 0xd0, 0xa2, 0x6f, + 0x9c, 0xe7, 0x5b, 0x2d, 0x92, 0x76, 0x67, 0x6f, 0x72, 0xe4, 0x1a, 0x36, 0x9e, 0x51, 0xef, 0x18, + 0x72, 0xb3, 0xc2, 0xa9, 0x15, 0xa3, 0x2c, 0x5c, 0xe5, 0xd0, 0x85, 0x5b, 0x4d, 0x00, 0x60, 0x0a, + 0x90, 0xbc, 0x02, 0x23, 0xdb, 0x74, 0x37, 0xd0, 0x37, 0xa4, 0x80, 0xa1, 0xc3, 0x08, 0x18, 0x67, + 0x26, 0xdc, 0xb5, 0x58, 0x76, 0x4c, 0x80, 0x11, 0x1f, 0x4e, 0x6f, 0x53, 0x6f, 0x83, 0x7a, 0xae, + 0x5c, 0x7d, 0x4a, 0x21, 0xc3, 0x87, 0x11, 0x32, 0xb1, 0xbf, 0x37, 0x79, 0xfa, 0x5a, 0x06, 0x0c, + 0x66, 0x82, 0x6b, 0xbf, 0x2c, 0xc2, 0x89, 0x45, 0xb1, 0x99, 0xeb, 0x7a, 0x62, 0x12, 0x26, 0x67, + 0xa1, 0xe4, 0x75, 0xba, 0xbc, 0xe5, 0x94, 0x84, 0xbb, 0x16, 0x57, 0xd7, 0x91, 0xd1, 0xc8, 0xcb, + 0x50, 0x35, 0xe5, 0x90, 0x21, 0x17, 0xbf, 0x03, 0x39, 0x2a, 0xd4, 0x1b, 0x86, 0x68, 0xcc, 0xd2, + 0x6f, 0xfb, 0xad, 0xa6, 0xf5, 0x06, 0x95, 0xeb, 0x41, 0x6e, 0xe9, 0xaf, 0x08, 0x12, 0xaa, 0x34, + 0x36, 0xab, 0x6e, 0xd3, 0x5d, 0xb1, 0x1a, 0x2a, 0x47, 0xb3, 0xea, 0x35, 0x49, 0xc3, 0x30, 0x95, + 0x4c, 0xaa, 0xce, 0xc2, 0x5a, 0x41, 0x59, 0xac, 0xe4, 0x6f, 0x32, 0x82, 0xec, 0x37, 0x6c, 0xc8, + 0x7c, 0xcd, 0x0a, 0x02, 0xea, 0xc9, 0xcf, 0x38, 0xd0, 0x90, 0x79, 0x95, 0x23, 0xa0, 0x44, 0x22, + 0x1f, 0x83, 0x1a, 0x07, 0x6f, 0xd8, 0xee, 0x06, 0xff, 0x70, 0x35, 0xb1, 0xa6, 0xbf, 0xa9, 0x88, + 0x18, 0xa5, 0x6b, 0xbf, 0x2e, 0xc2, 0x99, 0x45, 0x1a, 0x08, 0xab, 0x66, 0x9e, 0x76, 0x6c, 0x77, + 0x97, 0x99, 0x96, 0x48, 0x5f, 0x27, 0x2f, 0x02, 0x58, 0xfe, 0x46, 0x73, 0xc7, 0xe0, 0xfd, 0x40, + 0xf4, 0xe1, 0x8b, 0xb2, 0x4b, 0xc2, 0x52, 0xb3, 0x21, 0x53, 0xee, 0x24, 0xde, 0x30, 0x96, 0x27, + 0x5a, 0x5e, 0x15, 0xef, 0xb2, 0xbc, 0x6a, 0x02, 0x74, 0x22, 0x03, 0xb5, 0xc4, 0x39, 0xff, 0x95, + 0x12, 0x73, 0x18, 0xdb, 0x34, 0x06, 0x93, 0xc7, 0x64, 0x74, 0x60, 0xdc, 0xa4, 0x9b, 0x7a, 0xd7, + 0x0e, 0x42, 0xa3, 0x5a, 0x76, 0xe2, 0x83, 0xdb, 0xe5, 0xe1, 0x46, 0xf3, 0x7c, 0x0a, 0x09, 0x7b, + 0xb0, 0xb5, 0xff, 0x5f, 0x82, 0x73, 0x8b, 0x34, 0x08, 0x3d, 0x2e, 0x72, 0x74, 0x6c, 0x76, 0xa8, + 0xc1, 0xbe, 0xc2, 0x5b, 0x05, 0x18, 0xb2, 0xf5, 0x0d, 0x6a, 0xb3, 0xd9, 0x8b, 0xd5, 0xe6, 0xd5, + 0x81, 0x27, 0x82, 0xfe, 0x52, 0xa6, 0x96, 0xb9, 0x84, 0xd4, 0xd4, 0x20, 0x88, 0x28, 0xc5, 0xb3, + 0x41, 0xdd, 0xb0, 0xbb, 0x7e, 0x40, 0xbd, 0x55, 0xd7, 0x0b, 0xa4, 0x3d, 0x19, 0x0e, 0xea, 0x73, + 0x51, 0x12, 0xc6, 0xf9, 0xc8, 0x0c, 0x80, 0x61, 0x5b, 0xd4, 0x09, 0x78, 0x2e, 0xd1, 0xaf, 0x88, + 0xfa, 0xbe, 0x73, 0x61, 0x0a, 0xc6, 0xb8, 0x98, 0xa8, 0xb6, 0xeb, 0x58, 0x81, 0x2b, 0x44, 0x95, + 0x93, 0xa2, 0x56, 0xa2, 0x24, 0x8c, 0xf3, 0xf1, 0x6c, 0x34, 0xf0, 0x2c, 0xc3, 0xe7, 0xd9, 0x2a, + 0xa9, 0x6c, 0x51, 0x12, 0xc6, 0xf9, 0xd8, 0x9c, 0x17, 0xab, 0xff, 0xa1, 0xe6, 0xbc, 0xef, 0xd6, + 0xe0, 0x42, 0x42, 0xad, 0x81, 0x1e, 0xd0, 0xcd, 0xae, 0xdd, 0xa4, 0x81, 0xfa, 0x80, 0x03, 0xce, + 0x85, 0xff, 0x31, 0xfa, 0xee, 0x22, 0x84, 0xc4, 0x38, 0x9a, 0xef, 0xde, 0x53, 0xc0, 0x03, 0x7d, + 0xfb, 0x69, 0xa8, 0x39, 0x7a, 0xe0, 0xf3, 0x8e, 0x2b, 0xfb, 0x68, 0x68, 0x86, 0x5d, 0x57, 0x09, + 0x18, 0xf1, 0x90, 0x55, 0x38, 0x2d, 0x55, 0x7c, 0xf9, 0x76, 0xc7, 0xf5, 0x02, 0xea, 0x89, 0xbc, + 0x72, 0x3a, 0x95, 0x79, 0x4f, 0xaf, 0x64, 0xf0, 0x60, 0x66, 0x4e, 0xb2, 0x02, 0xa7, 0x0c, 0xb1, + 0xad, 0x4e, 0x6d, 0x57, 0x37, 0x15, 0xa0, 0x70, 0x70, 0x85, 0x4b, 0xa3, 0xb9, 0x5e, 0x16, 0xcc, + 0xca, 0x97, 0x6e, 0xcd, 0x43, 0x03, 0xb5, 0xe6, 0xe1, 0x41, 0x5a, 0x73, 0x75, 0xb0, 0xd6, 0x5c, + 0x3b, 0x58, 0x6b, 0x66, 0x9a, 0x67, 0xed, 0x88, 0x7a, 0xcc, 0x3c, 0x11, 0x33, 0x6c, 0x2c, 0x6a, + 0x23, 0xd4, 0x7c, 0x33, 0x83, 0x07, 0x33, 0x73, 0x92, 0x0d, 0x38, 0x27, 0xe8, 0x97, 0x1d, 0xc3, + 0xdb, 0xed, 0xb0, 0x89, 0x27, 0x86, 0x5b, 0x4f, 0x78, 0x18, 0xcf, 0x35, 0xfb, 0x72, 0xe2, 0x5d, + 0x50, 0xc8, 0xa7, 0x61, 0x54, 0x7c, 0xa5, 0x15, 0xbd, 0xc3, 0x61, 0x45, 0x0c, 0xc7, 0xc3, 0x12, + 0x76, 0x74, 0x2e, 0x9e, 0x88, 0x49, 0x5e, 0x32, 0x0b, 0x27, 0x3a, 0x3b, 0x06, 0x7b, 0x5c, 0xda, + 0xbc, 0x4e, 0xa9, 0x49, 0x4d, 0xbe, 0x69, 0x54, 0x6b, 0x3c, 0xa2, 0x1c, 0x1d, 0xab, 0xc9, 0x64, + 0x4c, 0xf3, 0x93, 0xe7, 0x61, 0xc4, 0x0f, 0x74, 0x2f, 0x90, 0x6e, 0xbd, 0x89, 0x31, 0x11, 0xe3, + 0xa2, 0xbc, 0x5e, 0xcd, 0x58, 0x1a, 0x26, 0x38, 0x33, 0xe7, 0x8b, 0x13, 0xc7, 0x37, 0x5f, 0xe4, + 0x19, 0xad, 0x7e, 0xaf, 0x08, 0x17, 0x17, 0x69, 0xb0, 0xe2, 0x3a, 0xd2, 0x29, 0x9a, 0x35, 0xed, + 0x1f, 0xc8, 0x27, 0x9a, 0x9c, 0xb4, 0x8b, 0x47, 0x3a, 0x69, 0x97, 0x8e, 0x68, 0xd2, 0x2e, 0x1f, + 0xe3, 0xa4, 0xfd, 0x9b, 0x45, 0x78, 0x24, 0xa1, 0xc9, 0x55, 0xd7, 0x54, 0x03, 0xfe, 0x07, 0x0a, + 0x3c, 0x80, 0x02, 0xef, 0x08, 0xbb, 0x93, 0x6f, 0x6b, 0xa5, 0x2c, 0x9e, 0x37, 0xd3, 0x16, 0xcf, + 0x2b, 0x79, 0x66, 0xbe, 0x0c, 0x09, 0x07, 0x9a, 0xf1, 0xae, 0x02, 0xf1, 0xe4, 0x26, 0x9c, 0x70, + 0xfd, 0xc4, 0x8c, 0x9e, 0x30, 0x88, 0x0e, 0x7b, 0x38, 0x30, 0x23, 0x17, 0x69, 0xc2, 0xc3, 0x3e, + 0x75, 0x02, 0xcb, 0xa1, 0x76, 0x12, 0x4e, 0x58, 0x43, 0x8f, 0x49, 0xb8, 0x87, 0x9b, 0x59, 0x4c, + 0x98, 0x9d, 0x37, 0xcf, 0x38, 0xf0, 0x07, 0xc0, 0x4d, 0x4e, 0xa1, 0x9a, 0x23, 0xb3, 0x58, 0xde, + 0x4a, 0x5b, 0x2c, 0xaf, 0xe6, 0xff, 0x6e, 0x83, 0x59, 0x2b, 0x33, 0x00, 0xfc, 0x2b, 0xc4, 0xcd, + 0x95, 0x70, 0x92, 0xc6, 0x30, 0x05, 0x63, 0x5c, 0x6c, 0x02, 0x52, 0x7a, 0x8e, 0x5b, 0x2a, 0xe1, + 0x04, 0xd4, 0x8c, 0x27, 0x62, 0x92, 0xb7, 0xaf, 0xb5, 0x53, 0x19, 0xd8, 0xda, 0xb9, 0x0a, 0x24, + 0xe1, 0x78, 0x14, 0x78, 0x43, 0xc9, 0x18, 0xce, 0xa5, 0x1e, 0x0e, 0xcc, 0xc8, 0xd5, 0xa7, 0x29, + 0x0f, 0x1f, 0x6d, 0x53, 0xae, 0x0e, 0xde, 0x94, 0xc9, 0xab, 0x70, 0x96, 0x8b, 0x92, 0xfa, 0x49, + 0x02, 0x0b, 0xbb, 0xe7, 0x43, 0x12, 0xf8, 0x2c, 0xf6, 0x63, 0xc4, 0xfe, 0x18, 0xec, 0xfb, 0x18, + 0x1e, 0x35, 0x99, 0x70, 0xdd, 0xee, 0x6f, 0x13, 0xcd, 0x65, 0xf0, 0x60, 0x66, 0x4e, 0xd6, 0xc4, + 0x02, 0xd6, 0x0c, 0xf5, 0x0d, 0x9b, 0x9a, 0x32, 0x86, 0x35, 0x6c, 0x62, 0x6b, 0xcb, 0x4d, 0x99, + 0x82, 0x31, 0xae, 0x2c, 0x33, 0x65, 0xe4, 0x90, 0x66, 0xca, 0x22, 0xf7, 0xd2, 0x6f, 0x26, 0xac, + 0x21, 0x69, 0xeb, 0x84, 0x51, 0xc9, 0x73, 0x69, 0x06, 0xec, 0xcd, 0xc3, 0xad, 0x44, 0xc3, 0xb3, + 0x3a, 0x81, 0x9f, 0xc4, 0x1a, 0x4b, 0x59, 0x89, 0x19, 0x3c, 0x98, 0x99, 0x93, 0xd9, 0xe7, 0x5b, + 0x54, 0xb7, 0x83, 0xad, 0x24, 0xe0, 0x89, 0xa4, 0x7d, 0x7e, 0xa5, 0x97, 0x05, 0xb3, 0xf2, 0x65, + 0x4e, 0x48, 0xe3, 0x0f, 0xa6, 0x59, 0xf5, 0x8d, 0x12, 0x9c, 0x5d, 0xa4, 0x41, 0x18, 0xde, 0xf3, + 0x81, 0x1b, 0xe5, 0x3d, 0x70, 0xa3, 0x7c, 0xa7, 0x02, 0xa7, 0x16, 0x69, 0xd0, 0x63, 0x8d, 0xfd, + 0x33, 0x55, 0xff, 0x0a, 0x9c, 0x8a, 0x22, 0xca, 0x9a, 0x81, 0xeb, 0x89, 0xb9, 0x3c, 0xb5, 0x5a, + 0x6e, 0xf6, 0xb2, 0x60, 0x56, 0x3e, 0xf2, 0x05, 0x78, 0x84, 0x4f, 0xf5, 0x4e, 0x4b, 0xf8, 0x67, + 0x85, 0x33, 0x21, 0x76, 0x26, 0x62, 0x52, 0x42, 0x3e, 0xd2, 0xcc, 0x66, 0xc3, 0x7e, 0xf9, 0xc9, + 0x57, 0x61, 0xa4, 0x63, 0x75, 0xa8, 0x6d, 0x39, 0xdc, 0x3e, 0xcb, 0x1d, 0x12, 0xb2, 0x1a, 0x03, + 0x8b, 0x16, 0x70, 0x71, 0x2a, 0x26, 0x04, 0x66, 0xb6, 0xd4, 0xea, 0x31, 0xb6, 0xd4, 0xbf, 0x2d, + 0xc2, 0xf0, 0xa2, 0xe7, 0x76, 0x3b, 0x8d, 0x5d, 0xd2, 0x82, 0xa1, 0x5b, 0x7c, 0xf3, 0x4c, 0x6e, + 0x4d, 0x0d, 0x1e, 0x95, 0x2d, 0xf6, 0xe0, 0x22, 0x93, 0x48, 0xbc, 0xa3, 0x84, 0x67, 0x8d, 0x78, + 0x9b, 0xee, 0x52, 0x53, 0xee, 0xa1, 0x85, 0x8d, 0xf8, 0x1a, 0x23, 0xa2, 0x48, 0x23, 0x6d, 0x38, + 0xa1, 0xdb, 0xb6, 0x7b, 0x8b, 0x9a, 0xcb, 0x7a, 0x40, 0x1d, 0xea, 0xab, 0x2d, 0xc9, 0xc3, 0xba, + 0xa5, 0xf9, 0xbe, 0xfe, 0x6c, 0x12, 0x0a, 0xd3, 0xd8, 0xe4, 0x35, 0x18, 0xf6, 0x03, 0xd7, 0x53, + 0xc6, 0x56, 0x7d, 0x66, 0x6e, 0xf0, 0x8f, 0xde, 0xf8, 0x7c, 0x53, 0x40, 0x09, 0x9f, 0xbd, 0x7c, + 0x41, 0x25, 0x40, 0xfb, 0x76, 0x01, 0xe0, 0xca, 0xda, 0xda, 0xaa, 0xdc, 0x5e, 0x30, 0xa1, 0xac, + 0x77, 0xc3, 0x8d, 0xca, 0xc1, 0x37, 0x04, 0x13, 0x61, 0x99, 0x72, 0x0f, 0xaf, 0x1b, 0x6c, 0x21, + 0x47, 0x27, 0x1f, 0x85, 0x61, 0x69, 0x20, 0x4b, 0xb5, 0x87, 0xa1, 0x05, 0xd2, 0x88, 0x46, 0x95, + 0xae, 0xfd, 0x9f, 0x22, 0xc0, 0x92, 0x69, 0xd3, 0xa6, 0x0a, 0xa4, 0xaf, 0x05, 0x5b, 0x1e, 0xf5, + 0xb7, 0x5c, 0xdb, 0x1c, 0x70, 0x37, 0x95, 0xfb, 0xfc, 0xd7, 0x14, 0x08, 0x46, 0x78, 0xc4, 0x84, + 0x11, 0x3f, 0xa0, 0x1d, 0x15, 0xa9, 0x39, 0xe0, 0x26, 0xca, 0xb8, 0xf0, 0x8b, 0x44, 0x38, 0x98, + 0x40, 0x25, 0x3a, 0xd4, 0x2d, 0xc7, 0x10, 0x1d, 0xa4, 0xb1, 0x3b, 0x60, 0x43, 0x3a, 0xc1, 0x56, + 0x1c, 0x4b, 0x11, 0x0c, 0xc6, 0x31, 0xb5, 0x9f, 0x15, 0xe1, 0x0c, 0x97, 0xc7, 0x8a, 0x91, 0x88, + 0xc7, 0x24, 0xff, 0xa6, 0xe7, 0xd0, 0xdf, 0xbf, 0x3c, 0x98, 0x68, 0x71, 0x66, 0x6c, 0x85, 0x06, + 0x7a, 0x64, 0xcf, 0x45, 0xb4, 0xd8, 0x49, 0xbf, 0x2e, 0x94, 0x7d, 0x36, 0x5e, 0x09, 0xed, 0x35, + 0x07, 0x6e, 0x42, 0xd9, 0x15, 0xe0, 0xa3, 0x57, 0xb8, 0x6b, 0xcc, 0x47, 0x2d, 0x2e, 0x8e, 0xfc, + 0x3b, 0x18, 0xf2, 0x03, 0x3d, 0xe8, 0xaa, 0xae, 0xb9, 0x7e, 0xd4, 0x82, 0x39, 0x78, 0x34, 0x8e, + 0x88, 0x77, 0x94, 0x42, 0xb5, 0x9f, 0x15, 0xe0, 0x5c, 0x76, 0xc6, 0x65, 0xcb, 0x0f, 0xc8, 0xbf, + 0xee, 0x51, 0xfb, 0x01, 0xbf, 0x38, 0xcb, 0xcd, 0x95, 0x1e, 0xc6, 0x85, 0x2b, 0x4a, 0x4c, 0xe5, + 0x01, 0x54, 0xac, 0x80, 0xb6, 0xd5, 0xfa, 0xf2, 0xc6, 0x11, 0x57, 0x3d, 0x36, 0xb5, 0x33, 0x29, + 0x28, 0x84, 0x69, 0x6f, 0x17, 0xfb, 0x55, 0x99, 0x4f, 0x1f, 0x76, 0x32, 0xe6, 0xf7, 0x5a, 0xbe, + 0x98, 0xdf, 0x64, 0x81, 0x7a, 0x43, 0x7f, 0xff, 0x6d, 0x6f, 0xe8, 0xef, 0x8d, 0xfc, 0xa1, 0xbf, + 0x29, 0x35, 0xf4, 0x8d, 0x00, 0x7e, 0xb7, 0x04, 0xe7, 0xef, 0xd6, 0x6c, 0xd8, 0x7c, 0x26, 0x5b, + 0x67, 0xde, 0xf9, 0xec, 0xee, 0xed, 0x90, 0xcc, 0x40, 0xa5, 0xb3, 0xa5, 0xfb, 0xca, 0x28, 0x53, + 0x0b, 0x96, 0xca, 0x2a, 0x23, 0xde, 0x61, 0x83, 0x06, 0x37, 0xe6, 0xf8, 0x2b, 0x0a, 0x56, 0x36, + 0x1c, 0xb7, 0xa9, 0xef, 0x47, 0x3e, 0x81, 0x70, 0x38, 0x5e, 0x11, 0x64, 0x54, 0xe9, 0x24, 0x80, + 0x21, 0xe1, 0x62, 0x96, 0x33, 0xd3, 0xe0, 0x81, 0x5c, 0x19, 0x61, 0xe2, 0x51, 0xa5, 0xe4, 0x6e, + 0x85, 0x94, 0x45, 0xa6, 0xa0, 0x1c, 0x44, 0x41, 0xbb, 0x6a, 0x69, 0x5e, 0xce, 0xb0, 0x4f, 0x39, + 0x1f, 0x5b, 0xd8, 0xbb, 0x1b, 0xdc, 0xa9, 0x6e, 0xca, 0xfd, 0x73, 0xcb, 0x75, 0xb8, 0x41, 0x56, + 0x8a, 0x16, 0xf6, 0x37, 0x7a, 0x38, 0x30, 0x23, 0x97, 0xf6, 0xc7, 0x55, 0x38, 0x93, 0xdd, 0x1e, + 0x98, 0xde, 0x76, 0xa8, 0xe7, 0x33, 0xec, 0x42, 0x52, 0x6f, 0x37, 0x05, 0x19, 0x55, 0xfa, 0xfb, + 0x3a, 0xe0, 0xec, 0x3b, 0x05, 0x38, 0xeb, 0xc9, 0x3d, 0xa2, 0xfb, 0x11, 0x74, 0xf6, 0x98, 0x70, + 0x67, 0xf4, 0x11, 0x88, 0xfd, 0xcb, 0x42, 0xfe, 0x57, 0x01, 0x26, 0xda, 0x29, 0x3f, 0xc7, 0x31, + 0x9e, 0x5b, 0xe3, 0x51, 0xf1, 0x2b, 0x7d, 0xe4, 0x61, 0xdf, 0x92, 0x90, 0xaf, 0x42, 0xbd, 0xc3, + 0xda, 0x85, 0x1f, 0x50, 0xc7, 0x50, 0x47, 0xd7, 0x06, 0xef, 0x49, 0xab, 0x11, 0x96, 0x0a, 0x45, + 0x13, 0xf6, 0x41, 0x2c, 0x01, 0xe3, 0x12, 0x1f, 0xf0, 0x83, 0x6a, 0x97, 0xa0, 0xea, 0xd3, 0x20, + 0xb0, 0x9c, 0x96, 0x58, 0x6f, 0xd4, 0x44, 0x5f, 0x69, 0x4a, 0x1a, 0x86, 0xa9, 0xe4, 0x63, 0x50, + 0xe3, 0x5b, 0x4e, 0xb3, 0x5e, 0xcb, 0x9f, 0xa8, 0xf1, 0x70, 0xb1, 0x51, 0x11, 0x00, 0x27, 0x89, + 0x18, 0xa5, 0x93, 0xa7, 0x61, 0x64, 0x83, 0x77, 0x5f, 0x79, 0x76, 0x59, 0xf8, 0xb8, 0xb8, 0xb5, + 0xd6, 0x88, 0xd1, 0x31, 0xc1, 0x45, 0x66, 0x00, 0x68, 0xb8, 0x2f, 0x97, 0xf6, 0x67, 0x45, 0x3b, + 0x76, 0x18, 0xe3, 0x22, 0x8f, 0x41, 0x29, 0xb0, 0x7d, 0xee, 0xc3, 0xaa, 0x46, 0x4b, 0xd0, 0xb5, + 0xe5, 0x26, 0x32, 0xba, 0xf6, 0xeb, 0x02, 0x9c, 0x48, 0x1d, 0x2e, 0x61, 0x59, 0xba, 0x9e, 0x2d, + 0x87, 0x91, 0x30, 0xcb, 0x3a, 0x2e, 0x23, 0xa3, 0x93, 0x57, 0xa5, 0x59, 0x5e, 0xcc, 0x79, 0x4d, + 0xc3, 0x75, 0x3d, 0xf0, 0x99, 0x1d, 0xde, 0x63, 0x91, 0xf3, 0x6d, 0xbe, 0xa8, 0x3c, 0x72, 0x1e, + 0x88, 0x6d, 0xf3, 0x45, 0x69, 0x98, 0xe0, 0x4c, 0x39, 0xfc, 0xca, 0x07, 0x71, 0xf8, 0x69, 0xdf, + 0x2c, 0xc6, 0x34, 0x20, 0x2d, 0xfb, 0x7b, 0x68, 0xe0, 0x49, 0x36, 0x81, 0x86, 0x93, 0x7b, 0x2d, + 0x3e, 0xff, 0xf1, 0xc9, 0x58, 0xa6, 0x92, 0x97, 0x84, 0xee, 0x4b, 0x39, 0x0f, 0xc3, 0xae, 0x2d, + 0x37, 0x45, 0x74, 0x95, 0xfa, 0x6a, 0xe1, 0x27, 0x28, 0x1f, 0xd3, 0x27, 0xd0, 0x7e, 0xbf, 0x04, + 0xf5, 0xab, 0xee, 0xc6, 0xfb, 0x24, 0x82, 0x3a, 0x7b, 0x9a, 0x2a, 0xbe, 0x87, 0xd3, 0xd4, 0x3a, + 0x3c, 0x12, 0x04, 0x76, 0x93, 0x1a, 0xae, 0x63, 0xfa, 0xb3, 0x9b, 0x01, 0xf5, 0x16, 0x2c, 0xc7, + 0xf2, 0xb7, 0xa8, 0x29, 0xb7, 0x93, 0x1e, 0xdd, 0xdf, 0x9b, 0x7c, 0x64, 0x6d, 0x6d, 0x39, 0x8b, + 0x05, 0xfb, 0xe5, 0xe5, 0xc3, 0x86, 0x38, 0x09, 0xc8, 0x4f, 0xca, 0xc8, 0x98, 0x1b, 0x31, 0x6c, + 0xc4, 0xe8, 0x98, 0xe0, 0xd2, 0xde, 0x29, 0x42, 0x2d, 0x3c, 0x80, 0x4f, 0x9e, 0x80, 0xe1, 0x0d, + 0xcf, 0xdd, 0xa6, 0x9e, 0xd8, 0xb9, 0x93, 0x27, 0x65, 0x1a, 0x82, 0x84, 0x2a, 0x8d, 0x3c, 0x0e, + 0x95, 0xc0, 0xed, 0x58, 0x46, 0xda, 0xa1, 0xb6, 0xc6, 0x88, 0x28, 0xd2, 0x8e, 0xaf, 0x81, 0x3f, + 0x99, 0x30, 0xed, 0x6a, 0x7d, 0x8d, 0xb1, 0x57, 0xa0, 0xec, 0xeb, 0xbe, 0x2d, 0xe7, 0xd3, 0x1c, + 0x67, 0xd9, 0x67, 0x9b, 0xcb, 0xf2, 0x2c, 0xfb, 0x6c, 0x73, 0x19, 0x39, 0xa8, 0xf6, 0x8b, 0x22, + 0xd4, 0x85, 0xde, 0xc4, 0xa8, 0x70, 0x94, 0x9a, 0x7b, 0x81, 0x87, 0x52, 0xf8, 0xdd, 0x36, 0xf5, + 0xb8, 0x9b, 0x49, 0x0e, 0x72, 0xf1, 0xfd, 0x81, 0x28, 0x31, 0x0c, 0xa7, 0x88, 0x48, 0x4a, 0xf5, + 0xe5, 0x63, 0x54, 0x7d, 0xe5, 0x40, 0xaa, 0x1f, 0x3a, 0x0e, 0xd5, 0xbf, 0x55, 0x84, 0xda, 0xb2, + 0xb5, 0x49, 0x8d, 0x5d, 0xc3, 0xe6, 0x67, 0x02, 0x4d, 0x6a, 0xd3, 0x80, 0x2e, 0x7a, 0xba, 0x41, + 0x57, 0xa9, 0x67, 0xf1, 0x0b, 0x6a, 0x58, 0xff, 0xe0, 0x23, 0x90, 0x3c, 0x13, 0x38, 0xdf, 0x87, + 0x07, 0xfb, 0xe6, 0x26, 0x4b, 0x30, 0x62, 0x52, 0xdf, 0xf2, 0xa8, 0xb9, 0x1a, 0x5b, 0xa8, 0x3c, + 0xa1, 0xa6, 0x9a, 0xf9, 0x58, 0xda, 0x9d, 0xbd, 0xc9, 0x51, 0xe5, 0xa0, 0x14, 0x2b, 0x96, 0x44, + 0x56, 0xd6, 0xe5, 0x3b, 0x7a, 0xd7, 0xcf, 0x2a, 0x63, 0xac, 0xcb, 0xaf, 0x66, 0xb3, 0x60, 0xbf, + 0xbc, 0x5a, 0x05, 0x4a, 0xcb, 0x6e, 0x4b, 0x7b, 0xbb, 0x04, 0xe1, 0x4d, 0x46, 0xe4, 0x3f, 0x14, + 0xa0, 0xae, 0x3b, 0x8e, 0x1b, 0xc8, 0x5b, 0x82, 0xc4, 0x0e, 0x3c, 0xe6, 0xbe, 0x30, 0x69, 0x6a, + 0x36, 0x02, 0x15, 0x9b, 0xb7, 0xe1, 0x86, 0x72, 0x2c, 0x05, 0xe3, 0xb2, 0x49, 0x37, 0xb5, 0x9f, + 0xbc, 0x92, 0xbf, 0x14, 0x07, 0xd8, 0x3d, 0x3e, 0xf7, 0x39, 0x18, 0x4f, 0x17, 0xf6, 0x30, 0xdb, + 0x41, 0xb9, 0x36, 0xe6, 0x8b, 0x00, 0x51, 0x4c, 0xc9, 0x7d, 0x70, 0x62, 0x59, 0x09, 0x27, 0xd6, + 0xe2, 0xe0, 0x0a, 0x0e, 0x0b, 0xdd, 0xd7, 0x71, 0xf5, 0x7a, 0xca, 0x71, 0xb5, 0x74, 0x14, 0xc2, + 0xee, 0xee, 0xac, 0xfa, 0xdf, 0x05, 0x18, 0x8f, 0x98, 0xe5, 0x09, 0xd9, 0xe7, 0x60, 0xd4, 0xa3, + 0xba, 0xd9, 0xd0, 0x03, 0x63, 0x8b, 0x87, 0x7a, 0x17, 0x78, 0x6c, 0xf6, 0xc9, 0xfd, 0xbd, 0xc9, + 0x51, 0x8c, 0x27, 0x60, 0x92, 0x8f, 0xe8, 0x50, 0x67, 0x84, 0x35, 0xab, 0x4d, 0xdd, 0x6e, 0x30, + 0xa0, 0xd7, 0x94, 0x2f, 0x58, 0x30, 0x82, 0xc1, 0x38, 0xa6, 0xf6, 0x6e, 0x01, 0xc6, 0xe2, 0x05, + 0x3e, 0x76, 0x8f, 0xda, 0x56, 0xd2, 0xa3, 0x36, 0x77, 0x04, 0xdf, 0xa4, 0x8f, 0x17, 0xed, 0x97, + 0xd5, 0x78, 0xd5, 0xb8, 0xe7, 0x2c, 0xee, 0x2c, 0x28, 0xdc, 0xd5, 0x59, 0xf0, 0xfe, 0xbf, 0xbc, + 0xa6, 0x9f, 0x95, 0x5b, 0x7e, 0x80, 0xad, 0xdc, 0xf7, 0xf2, 0x06, 0x9c, 0xd8, 0x2d, 0x2e, 0x43, + 0x39, 0x6e, 0x71, 0x69, 0x87, 0xb7, 0xb8, 0x0c, 0x1f, 0xd9, 0xa0, 0x73, 0x90, 0x9b, 0x5c, 0xaa, + 0xf7, 0xf5, 0x26, 0x97, 0xda, 0x71, 0xdd, 0xe4, 0x02, 0x79, 0x6f, 0x72, 0x79, 0xb3, 0x00, 0x63, + 0x66, 0xe2, 0xc4, 0x2c, 0xf7, 0x2d, 0xe4, 0x99, 0x6a, 0x92, 0x07, 0x70, 0xc5, 0x91, 0xa9, 0x24, + 0x0d, 0x53, 0x22, 0xb5, 0xff, 0x5b, 0x89, 0xcf, 0x03, 0xf7, 0xdb, 0x55, 0xfd, 0x6c, 0xd2, 0x55, + 0x7d, 0x31, 0xed, 0xaa, 0x3e, 0x11, 0x8b, 0x22, 0x8d, 0xbb, 0xab, 0x3f, 0x1e, 0x1b, 0x1e, 0x4b, + 0xfc, 0xe6, 0x94, 0x50, 0xd3, 0x19, 0x43, 0xe4, 0xc7, 0xa1, 0xea, 0xab, 0x3b, 0x27, 0xc5, 0xc2, + 0x26, 0xfa, 0x2e, 0xea, 0x3e, 0xc8, 0x90, 0x83, 0x59, 0xe2, 0x1e, 0xd5, 0x7d, 0xd7, 0x49, 0x5b, + 0xe2, 0xc8, 0xa9, 0x28, 0x53, 0xe3, 0x2e, 0xf3, 0xa1, 0x7b, 0xb8, 0xcc, 0x75, 0xa8, 0xdb, 0xba, + 0x1f, 0xac, 0x77, 0x4c, 0x3d, 0xa0, 0xa6, 0xec, 0x6f, 0xff, 0xe2, 0x60, 0x73, 0x15, 0x9b, 0xff, + 0x22, 0x83, 0x70, 0x39, 0x82, 0xc1, 0x38, 0x26, 0x31, 0x61, 0x84, 0xbd, 0xf2, 0xde, 0x60, 0xce, + 0xaa, 0x2b, 0x00, 0x0e, 0x23, 0x23, 0xf4, 0xf4, 0x2c, 0xc7, 0x70, 0x30, 0x81, 0xda, 0xc7, 0xab, + 0x5e, 0x1b, 0xc4, 0xab, 0x4e, 0x3e, 0x2d, 0x8c, 0x8d, 0x5d, 0xf5, 0xc1, 0xb8, 0x37, 0x6e, 0x34, + 0x8a, 0x2a, 0xc4, 0x78, 0x22, 0x26, 0x79, 0xb5, 0x37, 0x6b, 0x50, 0xbf, 0xae, 0x07, 0xd6, 0x0e, + 0xe5, 0x5b, 0x40, 0xc7, 0xe3, 0x87, 0xff, 0x6f, 0x05, 0x38, 0x93, 0x8c, 0xf3, 0x3b, 0x46, 0x67, + 0x3c, 0xbf, 0x35, 0x04, 0x33, 0xa5, 0x61, 0x9f, 0x52, 0x70, 0xb7, 0x7c, 0x4f, 0xd8, 0xe0, 0x71, + 0xbb, 0xe5, 0x9b, 0xfd, 0x04, 0x62, 0xff, 0xb2, 0xbc, 0x5f, 0xdc, 0xf2, 0x0f, 0xf6, 0xe5, 0x72, + 0xa9, 0x4d, 0x83, 0xe1, 0x07, 0x66, 0xd3, 0xa0, 0xfa, 0x40, 0x58, 0x6a, 0x9d, 0xd8, 0xa6, 0x41, + 0x2d, 0x67, 0xf0, 0x8a, 0x0c, 0x8d, 0x17, 0x68, 0xfd, 0x36, 0x1f, 0xf8, 0xa9, 0x76, 0xe5, 0xcc, + 0x65, 0x06, 0xce, 0x86, 0xee, 0x5b, 0x86, 0x9c, 0x33, 0x73, 0x5c, 0xa6, 0xa9, 0xae, 0xfb, 0x12, + 0x7b, 0xdc, 0xfc, 0x15, 0x05, 0x76, 0x74, 0xbb, 0x59, 0x31, 0xd7, 0xed, 0x66, 0x64, 0x0e, 0xca, + 0x0e, 0x5b, 0x7a, 0x97, 0x0e, 0x7d, 0x91, 0xd8, 0xf5, 0x6b, 0x74, 0x17, 0x79, 0x66, 0xed, 0x9d, + 0x22, 0x00, 0xab, 0xfe, 0xc1, 0xdc, 0xf7, 0x1f, 0x85, 0x61, 0xbf, 0xcb, 0x17, 0xda, 0x72, 0xb6, + 0x8f, 0x22, 0x7e, 0x04, 0x19, 0x55, 0x3a, 0x79, 0x1c, 0x2a, 0xaf, 0x77, 0x69, 0x57, 0xed, 0x45, + 0x87, 0xb6, 0xde, 0xe7, 0x19, 0x11, 0x45, 0xda, 0xf1, 0xb9, 0xe2, 0x94, 0x9b, 0xbf, 0x72, 0x5c, + 0x6e, 0xfe, 0x1a, 0x0c, 0x5f, 0x77, 0x79, 0x00, 0xa1, 0xf6, 0xd7, 0x45, 0x80, 0x28, 0x40, 0x8b, + 0x7c, 0xbb, 0x00, 0x0f, 0x87, 0x1d, 0x2e, 0x10, 0x26, 0x3b, 0xbf, 0xbf, 0x36, 0xb7, 0xcb, 0x3f, + 0xab, 0xb3, 0xf3, 0x11, 0x68, 0x35, 0x4b, 0x1c, 0x66, 0x97, 0x82, 0x20, 0x54, 0x69, 0xbb, 0x13, + 0xec, 0xce, 0x5b, 0x9e, 0x6c, 0x81, 0x99, 0x71, 0x80, 0x97, 0x25, 0x8f, 0xc8, 0x2a, 0xd7, 0x95, + 0xbc, 0x13, 0xa9, 0x14, 0x0c, 0x71, 0xc8, 0x16, 0x54, 0x1d, 0xf7, 0x55, 0x9f, 0xa9, 0x43, 0x36, + 0xc7, 0x17, 0x07, 0x57, 0xb9, 0x50, 0xab, 0x70, 0x11, 0xcb, 0x17, 0x1c, 0x76, 0xa4, 0xb2, 0xbf, + 0x55, 0x84, 0x53, 0x19, 0x7a, 0x20, 0x2f, 0xc2, 0xb8, 0x8c, 0x85, 0x8b, 0x2e, 0x72, 0x2e, 0x44, + 0x17, 0x39, 0x37, 0x53, 0x69, 0xd8, 0xc3, 0x4d, 0x5e, 0x05, 0xd0, 0x0d, 0x83, 0xfa, 0xfe, 0x8a, + 0x6b, 0x2a, 0x63, 0xf6, 0x85, 0xfd, 0xbd, 0x49, 0x98, 0x0d, 0xa9, 0x77, 0xf6, 0x26, 0x3f, 0x91, + 0x15, 0xde, 0x9a, 0xd2, 0x73, 0x94, 0x01, 0x63, 0x90, 0xe4, 0xcb, 0x00, 0x62, 0xdd, 0x16, 0x9e, + 0xc0, 0xbf, 0x87, 0xb3, 0x63, 0x4a, 0xdd, 0x75, 0x34, 0xf5, 0xf9, 0xae, 0xee, 0x04, 0x56, 0xb0, + 0x2b, 0x2e, 0x3c, 0xb9, 0x19, 0xa2, 0x60, 0x0c, 0x51, 0xfb, 0xdd, 0x22, 0x54, 0x95, 0x9b, 0xf5, + 0x3e, 0xf8, 0xd6, 0x5a, 0x09, 0xdf, 0xda, 0x11, 0x05, 0xb4, 0x66, 0x79, 0xd6, 0xdc, 0x94, 0x67, + 0x6d, 0x31, 0xbf, 0xa8, 0xbb, 0xfb, 0xd5, 0xbe, 0x57, 0x84, 0x31, 0xc5, 0x9a, 0xd7, 0xab, 0xf6, + 0x59, 0x38, 0x21, 0x36, 0xa2, 0x57, 0xf4, 0xdb, 0xe2, 0xee, 0x17, 0xae, 0xb0, 0xb2, 0x88, 0x21, + 0x6d, 0x24, 0x93, 0x30, 0xcd, 0xcb, 0x9a, 0xb5, 0x20, 0xad, 0xb3, 0x45, 0x88, 0xd8, 0xba, 0x12, + 0x8b, 0x25, 0xde, 0xac, 0x1b, 0xa9, 0x34, 0xec, 0xe1, 0x4e, 0xbb, 0xf5, 0xca, 0xc7, 0xe0, 0xd6, + 0xfb, 0x93, 0x02, 0x8c, 0x44, 0xfa, 0x3a, 0x76, 0xa7, 0xde, 0x66, 0xd2, 0xa9, 0x37, 0x9b, 0xbb, + 0x39, 0xf4, 0x71, 0xe9, 0xfd, 0xa7, 0x61, 0x48, 0xc4, 0x55, 0x93, 0x0d, 0x38, 0x67, 0x65, 0x46, + 0x87, 0xc5, 0x46, 0x9b, 0xf0, 0xa0, 0xf0, 0x52, 0x5f, 0x4e, 0xbc, 0x0b, 0x0a, 0xe9, 0x42, 0x75, + 0x87, 0x7a, 0x81, 0x65, 0x50, 0x55, 0xbf, 0xc5, 0xdc, 0x26, 0x99, 0x74, 0x5c, 0x86, 0x3a, 0xbd, + 0x29, 0x05, 0x60, 0x28, 0x8a, 0x6c, 0x40, 0x85, 0x9a, 0x2d, 0xaa, 0x6e, 0xe3, 0xc9, 0x79, 0xd7, + 0x65, 0xa8, 0x4f, 0xf6, 0xe6, 0xa3, 0x80, 0x26, 0x3e, 0xd4, 0x6c, 0xb5, 0x31, 0x25, 0xdb, 0xe1, + 0xe0, 0x06, 0x56, 0xb8, 0xc5, 0x15, 0x1d, 0xd4, 0x0f, 0x49, 0x18, 0xc9, 0x21, 0xdb, 0xa1, 0x87, + 0xac, 0x72, 0x44, 0x83, 0xc7, 0x5d, 0xfc, 0x63, 0x3e, 0xd4, 0x6e, 0xe9, 0x01, 0xf5, 0xda, 0xba, + 0xb7, 0x2d, 0x57, 0x1b, 0x83, 0xd7, 0xf0, 0x25, 0x85, 0x14, 0xd5, 0x30, 0x24, 0x61, 0x24, 0x87, + 0xb8, 0x50, 0x0b, 0xa4, 0xf9, 0xac, 0xdc, 0x80, 0x83, 0x0b, 0x55, 0x86, 0xb8, 0x2f, 0xe3, 0xab, + 0xd5, 0x2b, 0x46, 0x32, 0xc8, 0x4e, 0xe2, 0x3a, 0x62, 0x71, 0x09, 0x75, 0x23, 0x87, 0x3b, 0x59, + 0x42, 0x45, 0xd3, 0x4d, 0xf6, 0xb5, 0xc6, 0xda, 0x3b, 0x95, 0x68, 0x58, 0xbe, 0xdf, 0x4e, 0xae, + 0xa7, 0x93, 0x4e, 0xae, 0x0b, 0x69, 0x27, 0x57, 0x6a, 0x7f, 0xf3, 0xf0, 0x11, 0x99, 0x29, 0xf7, + 0x52, 0xf9, 0x18, 0xdc, 0x4b, 0x4f, 0x41, 0x7d, 0x87, 0x8f, 0x04, 0xe2, 0x6a, 0x9f, 0x0a, 0x9f, + 0x46, 0xf8, 0xc8, 0x7e, 0x33, 0x22, 0x63, 0x9c, 0x87, 0x65, 0x91, 0x3f, 0x60, 0x08, 0xef, 0x46, + 0x95, 0x59, 0x9a, 0x11, 0x19, 0xe3, 0x3c, 0x3c, 0x98, 0xcb, 0x72, 0xb6, 0x45, 0x86, 0x61, 0x9e, + 0x41, 0x04, 0x73, 0x29, 0x22, 0x46, 0xe9, 0xe4, 0x12, 0x54, 0xbb, 0xe6, 0xa6, 0xe0, 0xad, 0x72, + 0x5e, 0x6e, 0x61, 0xae, 0xcf, 0x2f, 0xc8, 0xab, 0x86, 0x54, 0x2a, 0x2b, 0x49, 0x5b, 0xef, 0xa8, + 0x04, 0xbe, 0x36, 0x94, 0x25, 0x59, 0x89, 0xc8, 0x18, 0xe7, 0x21, 0x9f, 0x82, 0x31, 0x8f, 0x9a, + 0x5d, 0x83, 0x86, 0xb9, 0x84, 0x77, 0x8a, 0x88, 0x3f, 0x4d, 0xc4, 0x53, 0x30, 0xc5, 0xd9, 0xc7, + 0x49, 0x56, 0x1f, 0x28, 0xf4, 0xf4, 0xa7, 0x05, 0x20, 0xbd, 0xc1, 0xcf, 0x64, 0x0b, 0x86, 0x1c, + 0xee, 0xfd, 0xca, 0x7d, 0x9b, 0x72, 0xcc, 0x89, 0x26, 0x86, 0x25, 0x49, 0x90, 0xf8, 0xc4, 0x81, + 0x2a, 0xbd, 0x1d, 0x50, 0xcf, 0x09, 0x0f, 0x43, 0x1c, 0xcd, 0xcd, 0xcd, 0x62, 0x35, 0x20, 0x91, + 0x31, 0x94, 0xa1, 0xfd, 0xbc, 0x08, 0xf5, 0x18, 0xdf, 0xbd, 0x16, 0x95, 0xfc, 0x3c, 0xb6, 0x70, + 0x3a, 0xad, 0x7b, 0xb6, 0xec, 0x61, 0xb1, 0xf3, 0xd8, 0x32, 0x09, 0x97, 0x31, 0xce, 0x47, 0x66, + 0x00, 0xda, 0xba, 0x1f, 0x50, 0x8f, 0xcf, 0xbe, 0xa9, 0x53, 0xd0, 0x2b, 0x61, 0x0a, 0xc6, 0xb8, + 0xc8, 0x45, 0x79, 0xf7, 0x76, 0x39, 0x79, 0x6b, 0x5d, 0x9f, 0x8b, 0xb5, 0x2b, 0x47, 0x70, 0xb1, + 0x36, 0x69, 0xc1, 0xb8, 0x2a, 0xb5, 0x4a, 0x3d, 0xdc, 0x9d, 0x66, 0x62, 0xfd, 0x92, 0x82, 0xc0, + 0x1e, 0x50, 0xed, 0x9d, 0x02, 0x8c, 0x26, 0x5c, 0x1e, 0xe2, 0xbe, 0x39, 0x15, 0xba, 0x9f, 0xb8, + 0x6f, 0x2e, 0x16, 0x71, 0xff, 0x24, 0x0c, 0x09, 0x05, 0xa5, 0x23, 0xf2, 0x84, 0x0a, 0x51, 0xa6, + 0xb2, 0xb1, 0x4c, 0x3a, 0x55, 0xd3, 0x63, 0x99, 0xf4, 0xba, 0xa2, 0x4a, 0x17, 0xbe, 0x7a, 0x51, + 0xba, 0x5e, 0x5f, 0xbd, 0xa0, 0x63, 0xc8, 0xa1, 0x7d, 0x9f, 0x97, 0x3b, 0xf0, 0x76, 0xc3, 0xb5, + 0x5c, 0x0b, 0x86, 0x65, 0x14, 0x96, 0xec, 0x1a, 0x2f, 0xe6, 0xf0, 0xc3, 0x70, 0x1c, 0x19, 0x6f, + 0xa4, 0x1b, 0xdb, 0x37, 0x36, 0x37, 0x51, 0xa1, 0x93, 0xcb, 0x50, 0x73, 0x9d, 0x05, 0xdd, 0xb2, + 0xbb, 0x9e, 0x1a, 0xd9, 0x3f, 0xc2, 0xc6, 0xaa, 0x1b, 0x8a, 0x78, 0x67, 0x6f, 0xf2, 0x4c, 0xf8, + 0x92, 0x28, 0x24, 0x46, 0x39, 0xb5, 0xbf, 0x2f, 0x01, 0x8f, 0xc0, 0x21, 0xcf, 0x41, 0xad, 0x4d, + 0x8d, 0x2d, 0xdd, 0xb1, 0x7c, 0x75, 0x63, 0x26, 0x5b, 0x9f, 0xd7, 0x56, 0x14, 0xf1, 0x0e, 0x53, + 0xc1, 0x6c, 0x73, 0x99, 0x07, 0xb9, 0x47, 0xbc, 0xc4, 0x80, 0xa1, 0x96, 0xef, 0xeb, 0x1d, 0x2b, + 0xf7, 0x06, 0xb0, 0xb8, 0xa1, 0x50, 0x0c, 0x03, 0xe2, 0x19, 0x25, 0x34, 0x31, 0xa0, 0xd2, 0xb1, + 0x75, 0xcb, 0xc9, 0xfd, 0xa7, 0x18, 0x56, 0x83, 0x55, 0x86, 0x24, 0x9c, 0x52, 0xfc, 0x11, 0x05, + 0x36, 0xe9, 0x42, 0xdd, 0x37, 0x3c, 0xbd, 0xed, 0x6f, 0xe9, 0x33, 0xcf, 0x3c, 0x9b, 0xdb, 0xcc, + 0x8b, 0x44, 0x89, 0x59, 0x67, 0x0e, 0x67, 0x57, 0x9a, 0x57, 0x66, 0x67, 0x9e, 0x79, 0x16, 0xe3, + 0x72, 0xe2, 0x62, 0x9f, 0x79, 0x6a, 0x46, 0xf6, 0xdc, 0x23, 0x17, 0xfb, 0xcc, 0x53, 0x33, 0x18, + 0x97, 0xa3, 0xfd, 0x5d, 0x01, 0x6a, 0x21, 0x2f, 0x59, 0x07, 0x60, 0x63, 0x88, 0xbc, 0x53, 0xf0, + 0x50, 0xf7, 0xfb, 0xf3, 0x75, 0xfd, 0x7a, 0x98, 0x19, 0x63, 0x40, 0x19, 0x97, 0x2e, 0x16, 0x8f, + 0xfa, 0xd2, 0xc5, 0x69, 0xa8, 0x6d, 0xe9, 0x8e, 0xe9, 0x6f, 0xe9, 0xdb, 0x62, 0x28, 0x8d, 0x5d, + 0x43, 0x7a, 0x45, 0x25, 0x60, 0xc4, 0xa3, 0xfd, 0xf6, 0x10, 0x88, 0x5d, 0x5b, 0xd6, 0xd9, 0x4d, + 0xcb, 0x17, 0x61, 0xc3, 0x05, 0x9e, 0x33, 0xec, 0xec, 0xf3, 0x92, 0x8e, 0x21, 0x07, 0x39, 0x0b, + 0xa5, 0xb6, 0xe5, 0xc8, 0x3d, 0x1b, 0xee, 0xb2, 0x5b, 0xb1, 0x1c, 0x64, 0x34, 0x9e, 0xa4, 0xdf, + 0x96, 0x11, 0x5f, 0x22, 0x49, 0xbf, 0x8d, 0x8c, 0xc6, 0x16, 0xd1, 0xb6, 0xeb, 0x6e, 0xb3, 0x6e, + 0xab, 0x02, 0xc3, 0xca, 0x7c, 0x2a, 0xe7, 0x8b, 0xe8, 0xe5, 0x64, 0x12, 0xa6, 0x79, 0xc9, 0x3a, + 0x3c, 0xf2, 0x06, 0xf5, 0x5c, 0x39, 0x4e, 0x35, 0x6d, 0x4a, 0x3b, 0x0a, 0x46, 0x18, 0x41, 0x3c, + 0xbe, 0xec, 0x8b, 0xd9, 0x2c, 0xd8, 0x2f, 0x2f, 0x8f, 0x54, 0xd5, 0xbd, 0x16, 0x0d, 0x56, 0x3d, + 0xd7, 0xa0, 0xbe, 0x6f, 0x39, 0x2d, 0x05, 0x3b, 0x14, 0xc1, 0xae, 0x65, 0xb3, 0x60, 0xbf, 0xbc, + 0xe4, 0x65, 0x98, 0x10, 0x49, 0xc2, 0x5c, 0x98, 0xdd, 0xd1, 0x2d, 0x5b, 0xdf, 0xb0, 0x6c, 0xf5, + 0x83, 0xb5, 0x51, 0xb1, 0x33, 0xb2, 0xd6, 0x87, 0x07, 0xfb, 0xe6, 0x26, 0x57, 0x61, 0x5c, 0xed, + 0x8b, 0xad, 0x52, 0xaf, 0x19, 0xee, 0xe4, 0x8f, 0x36, 0x2e, 0xb0, 0x15, 0xeb, 0x3c, 0xed, 0x78, + 0xd4, 0xe0, 0x76, 0x63, 0x8a, 0x0b, 0x7b, 0xf2, 0x11, 0x84, 0x33, 0x7c, 0xbb, 0x7e, 0xbd, 0x33, + 0xe7, 0xba, 0xb6, 0xe9, 0xde, 0x72, 0x54, 0xdd, 0x85, 0x69, 0xc6, 0xb7, 0xc2, 0x9a, 0x99, 0x1c, + 0xd8, 0x27, 0x27, 0xab, 0x39, 0x4f, 0x99, 0x77, 0x6f, 0x39, 0x69, 0x54, 0x88, 0x6a, 0xde, 0xec, + 0xc3, 0x83, 0x7d, 0x73, 0x93, 0x05, 0x20, 0xe9, 0x1a, 0xac, 0x77, 0xb8, 0x39, 0x37, 0xda, 0x38, + 0x23, 0xae, 0x07, 0x49, 0xa7, 0x62, 0x46, 0x0e, 0xb2, 0x0c, 0xa7, 0xd3, 0x54, 0x26, 0x8e, 0x9f, + 0x11, 0x18, 0x15, 0x17, 0x83, 0x62, 0x46, 0x3a, 0x66, 0xe6, 0xd2, 0x7e, 0xa7, 0x08, 0xa3, 0x89, + 0xf3, 0xe4, 0x0f, 0xdc, 0xb9, 0x5d, 0x66, 0x43, 0xb7, 0xfd, 0xd6, 0xd2, 0xfc, 0x15, 0xaa, 0x9b, + 0xd4, 0xbb, 0x46, 0xd5, 0xd9, 0x7f, 0x3e, 0xa8, 0xac, 0x24, 0x52, 0x30, 0xc5, 0x49, 0x36, 0xa1, + 0x22, 0x3c, 0xc2, 0x79, 0xff, 0x14, 0xa1, 0x74, 0xc4, 0xdd, 0xc2, 0xf2, 0xf7, 0x2a, 0xae, 0x47, + 0x51, 0xc0, 0x6b, 0x01, 0x8c, 0xc4, 0x39, 0xd8, 0x40, 0x12, 0x99, 0x9b, 0xc3, 0x09, 0x53, 0x73, + 0x09, 0x4a, 0x41, 0x30, 0xe8, 0x89, 0x60, 0xb1, 0xc3, 0xb0, 0xb6, 0x8c, 0x0c, 0x43, 0xdb, 0x64, + 0xdf, 0xce, 0xf7, 0x2d, 0xd7, 0x91, 0xd7, 0x43, 0xaf, 0xc3, 0x70, 0x20, 0x9d, 0x6c, 0x83, 0x9d, + 0x68, 0xe6, 0x36, 0x8a, 0x72, 0xb0, 0x29, 0x2c, 0xed, 0x4f, 0x8b, 0x50, 0x0b, 0x17, 0xc4, 0x07, + 0xb8, 0x76, 0xd9, 0x85, 0x5a, 0x18, 0x6e, 0x94, 0xfb, 0xe7, 0x73, 0x51, 0x14, 0x0c, 0x5f, 0xc3, + 0x85, 0xaf, 0x18, 0xc9, 0x88, 0x87, 0x32, 0x95, 0x72, 0x84, 0x32, 0x75, 0x60, 0x38, 0xf0, 0xac, + 0x56, 0x4b, 0x5a, 0xe7, 0x79, 0x62, 0x99, 0x42, 0x75, 0xad, 0x09, 0x40, 0xa9, 0x59, 0xf1, 0x82, + 0x4a, 0x8c, 0xf6, 0x1a, 0x8c, 0xa7, 0x39, 0xb9, 0xe9, 0x6a, 0x6c, 0x51, 0xb3, 0x6b, 0x2b, 0x1d, + 0x47, 0xa6, 0xab, 0xa4, 0x63, 0xc8, 0xc1, 0x96, 0xaf, 0xec, 0x33, 0xbd, 0xe1, 0x3a, 0xca, 0x7c, + 0xe4, 0xab, 0x80, 0x35, 0x49, 0xc3, 0x30, 0x55, 0xfb, 0xab, 0x12, 0x9c, 0x8d, 0xdc, 0x1a, 0x2b, + 0xba, 0xa3, 0xb7, 0x0e, 0xf0, 0xc7, 0xb1, 0x0f, 0xce, 0x88, 0x1c, 0xf6, 0xee, 0xfc, 0xd2, 0x03, + 0x70, 0x77, 0xfe, 0x3f, 0x14, 0x81, 0x87, 0x46, 0x92, 0xaf, 0xc2, 0x88, 0x1e, 0xfb, 0xd9, 0xa4, + 0xfc, 0x9c, 0x97, 0x73, 0x7f, 0x4e, 0x1e, 0x81, 0x19, 0x86, 0xfa, 0xc4, 0xa9, 0x98, 0x10, 0x48, + 0x5c, 0xa8, 0x6e, 0xea, 0xb6, 0xcd, 0x6c, 0xa1, 0xdc, 0xdb, 0x34, 0x09, 0xe1, 0xbc, 0x99, 0x2f, + 0x48, 0x68, 0x0c, 0x85, 0x90, 0x37, 0x0b, 0x30, 0xea, 0xc5, 0x97, 0x49, 0xf2, 0x83, 0xe4, 0xd9, + 0xc4, 0x8f, 0xa1, 0xc5, 0x03, 0x8b, 0xe2, 0x6b, 0xb1, 0xa4, 0x4c, 0xed, 0x2f, 0x0b, 0x30, 0xda, + 0xb4, 0x2d, 0xd3, 0x72, 0x5a, 0xc7, 0x78, 0x75, 0xff, 0x0d, 0xa8, 0xf8, 0xb6, 0x65, 0xd2, 0x01, + 0x67, 0x13, 0x31, 0x8f, 0x31, 0x00, 0x14, 0x38, 0xc9, 0x7f, 0x01, 0x94, 0x0e, 0xf0, 0x2f, 0x80, + 0x5f, 0x0d, 0x81, 0x0c, 0xf2, 0x25, 0x5d, 0xa8, 0xb5, 0xd4, 0x15, 0xe3, 0xb2, 0x8e, 0x57, 0x72, + 0x5c, 0x4f, 0x97, 0xb8, 0xac, 0x5c, 0x8c, 0xfd, 0x21, 0x11, 0x23, 0x49, 0x84, 0x26, 0xff, 0x72, + 0x3a, 0x9f, 0xf3, 0x2f, 0xa7, 0x42, 0x5c, 0xef, 0x7f, 0x4e, 0x75, 0x28, 0x6f, 0x05, 0x41, 0x47, + 0x36, 0xa6, 0xc1, 0xa3, 0xb8, 0xa3, 0x1b, 0x52, 0x84, 0x4d, 0xc4, 0xde, 0x91, 0x43, 0x33, 0x11, + 0x8e, 0x1e, 0xfe, 0xd5, 0x6a, 0x2e, 0x57, 0xc0, 0x40, 0x5c, 0x04, 0x7b, 0x47, 0x0e, 0x4d, 0xbe, + 0x02, 0xf5, 0xc0, 0xd3, 0x1d, 0x7f, 0xd3, 0xf5, 0xda, 0xd4, 0x93, 0x6b, 0xd4, 0x85, 0x1c, 0x3f, + 0xfa, 0x5c, 0x8b, 0xd0, 0xc4, 0x4e, 0x64, 0x82, 0x84, 0x71, 0x69, 0x64, 0x1b, 0xaa, 0x5d, 0x53, + 0x14, 0x4c, 0xba, 0x9f, 0x66, 0xf3, 0xfc, 0xbb, 0x35, 0x16, 0x0e, 0xa0, 0xde, 0x30, 0x14, 0x90, + 0xfc, 0x81, 0xdb, 0xf0, 0x51, 0xfd, 0xc0, 0x2d, 0xde, 0x1a, 0xb3, 0xae, 0x6f, 0x20, 0x6d, 0x69, + 0xd7, 0x3a, 0x2d, 0x19, 0xcd, 0xb4, 0x90, 0xdb, 0xe4, 0x14, 0x22, 0xeb, 0xa1, 0x6d, 0xec, 0xb4, + 0x50, 0xc9, 0xd0, 0xda, 0x20, 0x77, 0x09, 0x88, 0x91, 0xf8, 0xcd, 0x89, 0x38, 0x53, 0x34, 0x7d, + 0xb0, 0xf1, 0x20, 0xfc, 0xdf, 0x46, 0xec, 0x9a, 0xe5, 0xcc, 0xff, 0x99, 0x68, 0x7f, 0x56, 0x84, + 0xd2, 0xda, 0x72, 0x53, 0x5c, 0x9d, 0xc8, 0xff, 0x21, 0x44, 0x9b, 0xdb, 0x56, 0xe7, 0x26, 0xf5, + 0xac, 0xcd, 0x5d, 0xb9, 0xf4, 0x8e, 0x5d, 0x9d, 0x98, 0xe6, 0xc0, 0x8c, 0x5c, 0xe4, 0x15, 0x18, + 0x31, 0xf4, 0x39, 0xea, 0x05, 0x83, 0x38, 0x16, 0xf8, 0xe1, 0xc9, 0xb9, 0xd9, 0x28, 0x3b, 0x26, + 0xc0, 0xc8, 0x3a, 0x80, 0x11, 0x41, 0x97, 0x0e, 0xed, 0x0e, 0x89, 0x01, 0xc7, 0x80, 0x08, 0x42, + 0x6d, 0x9b, 0xb1, 0x72, 0xd4, 0xf2, 0x61, 0x50, 0x79, 0xcb, 0xb9, 0xa6, 0xf2, 0x62, 0x04, 0xa3, + 0x39, 0x30, 0x9a, 0xf8, 0xf7, 0x09, 0xf9, 0x24, 0x54, 0xdd, 0x4e, 0x6c, 0x38, 0xad, 0xf1, 0xb8, + 0xc9, 0xea, 0x0d, 0x49, 0xbb, 0xb3, 0x37, 0x39, 0xba, 0xec, 0xb6, 0x2c, 0x43, 0x11, 0x30, 0x64, + 0x27, 0x1a, 0x0c, 0xf1, 0x13, 0x4f, 0xea, 0xcf, 0x27, 0x7c, 0xee, 0xe0, 0x3f, 0x27, 0xf0, 0x51, + 0xa6, 0x68, 0x5f, 0x2b, 0x43, 0xb4, 0xb7, 0x46, 0x7c, 0x18, 0x12, 0x11, 0xdd, 0x72, 0xe4, 0x3e, + 0xd6, 0xe0, 0x71, 0x29, 0x8a, 0xb4, 0xa0, 0xf4, 0x9a, 0xbb, 0x91, 0x7b, 0xe0, 0x8e, 0x1d, 0x75, + 0x16, 0xbe, 0xb2, 0x18, 0x01, 0x99, 0x04, 0xf2, 0xdf, 0x0b, 0x70, 0xd2, 0x4f, 0x9b, 0xbe, 0xb2, + 0x39, 0x60, 0x7e, 0x1b, 0x3f, 0x6d, 0x4c, 0xcb, 0x00, 0xd7, 0x7e, 0xc9, 0xd8, 0x5b, 0x16, 0xa6, + 0x7f, 0xb1, 0xe9, 0x25, 0x9b, 0xd3, 0x62, 0xce, 0xff, 0xf5, 0x25, 0xf5, 0x9f, 0xa4, 0xa1, 0x14, + 0xa5, 0x7d, 0xa3, 0x08, 0xf5, 0xd8, 0x68, 0x9d, 0xfb, 0x87, 0x3a, 0xb7, 0x53, 0x3f, 0xd4, 0x59, + 0x1d, 0x7c, 0x0f, 0x38, 0x2a, 0xd5, 0x71, 0xff, 0x53, 0xe7, 0x47, 0x45, 0x28, 0xad, 0xcf, 0x2f, + 0x24, 0x17, 0xad, 0x85, 0xfb, 0xb0, 0x68, 0xdd, 0x82, 0xe1, 0x8d, 0xae, 0x65, 0x07, 0x96, 0x93, + 0xfb, 0x32, 0x06, 0xf5, 0xff, 0x21, 0xb9, 0xc7, 0x20, 0x50, 0x51, 0xc1, 0x93, 0x16, 0x0c, 0xb7, + 0xc4, 0x6d, 0x78, 0xb9, 0x23, 0xe3, 0xe4, 0xad, 0x7a, 0x42, 0x90, 0x7c, 0x41, 0x85, 0xae, 0xed, + 0x82, 0xfc, 0x91, 0xfa, 0x7d, 0xd7, 0xa6, 0xf6, 0x15, 0x08, 0xad, 0x80, 0xfb, 0x2f, 0xfc, 0x6f, + 0x0a, 0x90, 0x34, 0x7c, 0xee, 0x7f, 0x6b, 0xda, 0x4e, 0xb7, 0xa6, 0xf9, 0xa3, 0xe8, 0x7c, 0xd9, + 0x0d, 0x4a, 0xfb, 0xad, 0x22, 0x0c, 0xdd, 0xb7, 0x03, 0xb4, 0x34, 0x11, 0xe4, 0x37, 0x97, 0x73, + 0x60, 0xec, 0x1b, 0xe2, 0xd7, 0x4e, 0x85, 0xf8, 0xe5, 0xfd, 0x63, 0xea, 0x3d, 0x02, 0xfc, 0xfe, + 0xa8, 0x00, 0x72, 0x58, 0x5e, 0x72, 0xfc, 0x40, 0x77, 0x0c, 0x4a, 0x8c, 0x70, 0x0e, 0xc8, 0x1b, + 0x49, 0x22, 0xa3, 0xad, 0xc4, 0xb4, 0xcf, 0x9f, 0xd5, 0x98, 0x4f, 0x3e, 0x0e, 0xd5, 0x2d, 0xd7, + 0x0f, 0xf8, 0x38, 0x5f, 0x4c, 0x7a, 0x97, 0xae, 0x48, 0x3a, 0x86, 0x1c, 0xe9, 0x1d, 0xd7, 0x4a, + 0xff, 0x1d, 0x57, 0xed, 0xbb, 0x45, 0x18, 0x79, 0xbf, 0x9c, 0x02, 0xce, 0x0a, 0x89, 0x2c, 0xe5, + 0x0c, 0x89, 0x2c, 0x1f, 0x26, 0x24, 0x52, 0xfb, 0x71, 0x01, 0xe0, 0xbe, 0x1d, 0x41, 0x36, 0x93, + 0xd1, 0x8a, 0xb9, 0xdb, 0x55, 0x76, 0xac, 0xe2, 0x6f, 0x54, 0x54, 0x95, 0x78, 0xa4, 0xe2, 0x5b, + 0x05, 0x18, 0xd3, 0x13, 0xd1, 0x7f, 0xb9, 0x4d, 0xcb, 0x54, 0x30, 0x61, 0x78, 0xdc, 0x32, 0x49, + 0xc7, 0x94, 0x58, 0xf2, 0x7c, 0x74, 0xfd, 0xed, 0xf5, 0xa8, 0xd9, 0xf7, 0xdc, 0x5b, 0xcb, 0xcd, + 0x9c, 0x04, 0xe7, 0x3d, 0xa2, 0x2d, 0x4b, 0x47, 0x12, 0x6d, 0x19, 0x3f, 0x47, 0x56, 0xbe, 0xeb, + 0x39, 0xb2, 0x1d, 0xa8, 0x6d, 0x7a, 0x6e, 0x9b, 0x07, 0x34, 0xca, 0x7f, 0xad, 0x5e, 0xce, 0x31, + 0xa7, 0x44, 0x7f, 0x19, 0x8f, 0x7c, 0x3c, 0x0b, 0x0a, 0x1f, 0x23, 0x51, 0xdc, 0x2d, 0xee, 0x0a, + 0xa9, 0x43, 0x47, 0x29, 0x35, 0x1c, 0x4b, 0xd6, 0x04, 0x3a, 0x2a, 0x31, 0xc9, 0x20, 0xc6, 0xe1, + 0xfb, 0x13, 0xc4, 0xa8, 0xfd, 0xa8, 0xac, 0x06, 0xb0, 0x07, 0xee, 0xa6, 0xc5, 0xf7, 0xff, 0xd1, + 0xd5, 0xf4, 0xb9, 0xd2, 0xe1, 0xfb, 0x78, 0xae, 0xb4, 0x7a, 0x34, 0xe7, 0x4a, 0x6b, 0x87, 0x38, + 0x57, 0xba, 0x57, 0x82, 0xd4, 0xa2, 0xeb, 0x83, 0x0d, 0x96, 0x7f, 0x52, 0x1b, 0x2c, 0x6f, 0x17, + 0x21, 0x1a, 0x45, 0x0e, 0x19, 0x80, 0xf2, 0x32, 0x54, 0xdb, 0xfa, 0xed, 0x79, 0x6a, 0xeb, 0xbb, + 0x79, 0xfe, 0xae, 0xb9, 0x22, 0x31, 0x30, 0x44, 0x23, 0x3e, 0x80, 0x15, 0xde, 0x70, 0x9d, 0xdb, + 0x55, 0x1d, 0x5d, 0x96, 0x2d, 0x9c, 0x61, 0xd1, 0x3b, 0xc6, 0xc4, 0x68, 0x7f, 0x58, 0x04, 0x79, + 0x15, 0x3a, 0xa1, 0x50, 0xd9, 0xb4, 0x6e, 0x53, 0x33, 0x77, 0x38, 0x69, 0xec, 0x9f, 0xc7, 0xc2, + 0x17, 0xcf, 0x09, 0x28, 0xd0, 0xb9, 0x93, 0x55, 0xec, 0xad, 0x48, 0xfd, 0xe5, 0x70, 0xb2, 0xc6, + 0xf7, 0x68, 0xa4, 0x93, 0x55, 0x90, 0x50, 0xc9, 0x10, 0x3e, 0x5d, 0xbe, 0xcd, 0x9e, 0x7b, 0x2b, + 0x29, 0xb1, 0x5d, 0xaf, 0x7c, 0xba, 0xbe, 0x38, 0x58, 0x2e, 0x65, 0x34, 0xbe, 0xf4, 0xc3, 0x9f, + 0x5c, 0x78, 0xe8, 0xc7, 0x3f, 0xb9, 0xf0, 0xd0, 0xbb, 0x3f, 0xb9, 0xf0, 0xd0, 0xd7, 0xf6, 0x2f, + 0x14, 0x7e, 0xb8, 0x7f, 0xa1, 0xf0, 0xe3, 0xfd, 0x0b, 0x85, 0x77, 0xf7, 0x2f, 0x14, 0xfe, 0x7c, + 0xff, 0x42, 0xe1, 0xbf, 0xfc, 0xc5, 0x85, 0x87, 0xbe, 0xf8, 0x5c, 0x54, 0x84, 0x69, 0x55, 0x84, + 0x69, 0x25, 0x70, 0xba, 0xb3, 0xdd, 0x9a, 0x66, 0x45, 0x88, 0x28, 0xaa, 0x08, 0xff, 0x18, 0x00, + 0x00, 0xff, 0xff, 0xa1, 0xe2, 0x38, 0xfd, 0x6e, 0x95, 0x00, 0x00, } func (m *AbstractPodTemplate) Marshal() (dAtA []byte, err error) { @@ -3643,6 +3709,46 @@ func (m *Authorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Backoff) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Backoff) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Backoff) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Steps != nil { + i = encodeVarintGenerated(dAtA, i, uint64(*m.Steps)) + i-- + dAtA[i] = 0x10 + } + if m.Interval != nil { + { + size, err := m.Interval.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *BasicAuth) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7304,6 +7410,48 @@ func (m *RedisSettings) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *RetryStrategy) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RetryStrategy) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RetryStrategy) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.OnFailure != nil { + i -= len(*m.OnFailure) + copy(dAtA[i:], *m.OnFailure) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.OnFailure))) + i-- + dAtA[i] = 0x12 + } + if m.BackOff != nil { + { + size, err := m.BackOff.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *SASL) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7840,6 +7988,16 @@ func (m *Sink) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.RetryStrategy.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a if m.Fallback != nil { { size, err := m.Fallback.MarshalToSizedBuffer(dAtA[:i]) @@ -9198,6 +9356,22 @@ func (m *Authorization) Size() (n int) { return n } +func (m *Backoff) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Interval != nil { + l = m.Interval.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.Steps != nil { + n += 1 + sovGenerated(uint64(*m.Steps)) + } + return n +} + func (m *BasicAuth) Size() (n int) { if m == nil { return 0 @@ -10544,6 +10718,23 @@ func (m *RedisSettings) Size() (n int) { return n } +func (m *RetryStrategy) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BackOff != nil { + l = m.BackOff.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.OnFailure != nil { + l = len(*m.OnFailure) + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *SASL) Size() (n int) { if m == nil { return 0 @@ -10757,6 +10948,8 @@ func (m *Sink) Size() (n int) { l = m.Fallback.Size() n += 1 + l + sovGenerated(uint64(l)) } + l = m.RetryStrategy.Size() + n += 1 + l + sovGenerated(uint64(l)) return n } @@ -11289,6 +11482,17 @@ func (this *Authorization) String() string { }, "") return s } +func (this *Backoff) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Backoff{`, + `Interval:` + strings.Replace(fmt.Sprintf("%v", this.Interval), "Duration", "v11.Duration", 1) + `,`, + `Steps:` + valueToStringGenerated(this.Steps) + `,`, + `}`, + }, "") + return s +} func (this *BasicAuth) String() string { if this == nil { return "nil" @@ -12238,6 +12442,17 @@ func (this *RedisSettings) String() string { }, "") return s } +func (this *RetryStrategy) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RetryStrategy{`, + `BackOff:` + strings.Replace(this.BackOff.String(), "Backoff", "Backoff", 1) + `,`, + `OnFailure:` + valueToStringGenerated(this.OnFailure) + `,`, + `}`, + }, "") + return s +} func (this *SASL) String() string { if this == nil { return "nil" @@ -12367,6 +12582,7 @@ func (this *Sink) String() string { s := strings.Join([]string{`&Sink{`, `AbstractSink:` + strings.Replace(strings.Replace(this.AbstractSink.String(), "AbstractSink", "AbstractSink", 1), `&`, ``, 1) + `,`, `Fallback:` + strings.Replace(this.Fallback.String(), "AbstractSink", "AbstractSink", 1) + `,`, + `RetryStrategy:` + strings.Replace(strings.Replace(this.RetryStrategy.String(), "RetryStrategy", "RetryStrategy", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -14085,6 +14301,112 @@ func (m *Authorization) Unmarshal(dAtA []byte) error { } return nil } +func (m *Backoff) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Backoff: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Backoff: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Interval", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Interval == nil { + m.Interval = &v11.Duration{} + } + if err := m.Interval.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Steps", wireType) + } + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Steps = &v + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *BasicAuth) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -26019,6 +26341,125 @@ func (m *RedisSettings) Unmarshal(dAtA []byte) error { } return nil } +func (m *RetryStrategy) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RetryStrategy: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RetryStrategy: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BackOff", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BackOff == nil { + m.BackOff = &Backoff{} + } + if err := m.BackOff.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OnFailure", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := OnFailureRetryStrategy(dAtA[iNdEx:postIndex]) + m.OnFailure = &s + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *SASL) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -27614,6 +28055,39 @@ func (m *Sink) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RetryStrategy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.RetryStrategy.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/pkg/apis/numaflow/v1alpha1/generated.proto b/pkg/apis/numaflow/v1alpha1/generated.proto index 8c5a6db0f2..9c513d6fde 100644 --- a/pkg/apis/numaflow/v1alpha1/generated.proto +++ b/pkg/apis/numaflow/v1alpha1/generated.proto @@ -209,6 +209,18 @@ message Authorization { optional k8s.io.api.core.v1.SecretKeySelector token = 1; } +// Backoff defines parameters used to systematically configure the retry strategy. +message Backoff { + // Interval sets the delay to wait before retry, after a failure occurs. + // +kubebuilder:default="1ms" + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.Duration interval = 1; + + // Steps defines the number of times to try writing to a sink including retries + // +optional + optional uint32 steps = 2; +} + // BasicAuth represents the basic authentication approach which contains a user name and a password. message BasicAuth { // Secret for auth user @@ -1248,6 +1260,19 @@ message RedisSettings { optional string sentinel = 4; } +// RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. +// It includes a BackOff strategy to manage the timing of retries and defines the action to take upon failure. +message RetryStrategy { + // BackOff specifies the parameters for the backoff strategy, controlling how delays between retries should increase. + // +optional + optional Backoff backoff = 1; + + // OnFailure specifies the action to take when a retry fails. The default action is to retry. + // +optional + // +kubebuilder:default="retry" + optional string onFailure = 2; +} + message SASL { // SASL mechanism to use optional string mechanism = 1; @@ -1418,6 +1443,10 @@ message Sink { // initiated if the ud-sink response field sets it. // +optional optional AbstractSink fallback = 2; + + // RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. + // +optional + optional RetryStrategy retryStrategy = 3; } // SlidingWindow describes a sliding window diff --git a/pkg/apis/numaflow/v1alpha1/openapi_generated.go b/pkg/apis/numaflow/v1alpha1/openapi_generated.go index 8ed0f228c0..79aab81c33 100644 --- a/pkg/apis/numaflow/v1alpha1/openapi_generated.go +++ b/pkg/apis/numaflow/v1alpha1/openapi_generated.go @@ -34,6 +34,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.AbstractSink": schema_pkg_apis_numaflow_v1alpha1_AbstractSink(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.AbstractVertex": schema_pkg_apis_numaflow_v1alpha1_AbstractVertex(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Authorization": schema_pkg_apis_numaflow_v1alpha1_Authorization(ref), + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Backoff": schema_pkg_apis_numaflow_v1alpha1_Backoff(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.BasicAuth": schema_pkg_apis_numaflow_v1alpha1_BasicAuth(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Blackhole": schema_pkg_apis_numaflow_v1alpha1_Blackhole(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.BufferServiceConfig": schema_pkg_apis_numaflow_v1alpha1_BufferServiceConfig(ref), @@ -91,6 +92,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RedisBufferService": schema_pkg_apis_numaflow_v1alpha1_RedisBufferService(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RedisConfig": schema_pkg_apis_numaflow_v1alpha1_RedisConfig(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RedisSettings": schema_pkg_apis_numaflow_v1alpha1_RedisSettings(ref), + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RetryStrategy": schema_pkg_apis_numaflow_v1alpha1_RetryStrategy(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.SASL": schema_pkg_apis_numaflow_v1alpha1_SASL(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.SASLPlain": schema_pkg_apis_numaflow_v1alpha1_SASLPlain(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Scale": schema_pkg_apis_numaflow_v1alpha1_Scale(ref), @@ -608,6 +610,34 @@ func schema_pkg_apis_numaflow_v1alpha1_Authorization(ref common.ReferenceCallbac } } +func schema_pkg_apis_numaflow_v1alpha1_Backoff(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Backoff defines parameters used to systematically configure the retry strategy.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "interval": { + SchemaProps: spec.SchemaProps{ + Description: "Interval sets the delay to wait before retry, after a failure occurs.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), + }, + }, + "steps": { + SchemaProps: spec.SchemaProps{ + Description: "Steps defines the number of times to try writing to a sink including retries", + Type: []string{"integer"}, + Format: "int64", + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"}, + } +} + func schema_pkg_apis_numaflow_v1alpha1_BasicAuth(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -4202,6 +4232,34 @@ func schema_pkg_apis_numaflow_v1alpha1_RedisSettings(ref common.ReferenceCallbac } } +func schema_pkg_apis_numaflow_v1alpha1_RetryStrategy(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. It includes a BackOff strategy to manage the timing of retries and defines the action to take upon failure.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "backoff": { + SchemaProps: spec.SchemaProps{ + Description: "BackOff specifies the parameters for the backoff strategy, controlling how delays between retries should increase.", + Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Backoff"), + }, + }, + "onFailure": { + SchemaProps: spec.SchemaProps{ + Description: "OnFailure specifies the action to take when a retry fails. The default action is to retry.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Backoff"}, + } +} + func schema_pkg_apis_numaflow_v1alpha1_SASL(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -4748,11 +4806,18 @@ func schema_pkg_apis_numaflow_v1alpha1_Sink(ref common.ReferenceCallback) common Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.AbstractSink"), }, }, + "retryStrategy": { + SchemaProps: spec.SchemaProps{ + Description: "RetryStrategy struct encapsulates the settings for retrying operations in the event of failures.", + Default: map[string]interface{}{}, + Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RetryStrategy"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.AbstractSink", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Blackhole", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.KafkaSink", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Log", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDSink"}, + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.AbstractSink", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Blackhole", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.KafkaSink", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Log", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RetryStrategy", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDSink"}, } } diff --git a/pkg/apis/numaflow/v1alpha1/retry_strategy.go b/pkg/apis/numaflow/v1alpha1/retry_strategy.go new file mode 100644 index 0000000000..12c9daab4b --- /dev/null +++ b/pkg/apis/numaflow/v1alpha1/retry_strategy.go @@ -0,0 +1,102 @@ +/* +Copyright 2022 The Numaproj Authors. + +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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +type OnFailureRetryStrategy string + +// Constants representing the possible actions that can be taken when a failure occurs during an operation. +const ( + OnFailureRetry OnFailureRetryStrategy = "retry" // Retry the operation. + OnFailureFallback OnFailureRetryStrategy = "fallback" // Reroute the operation to a fallback mechanism. + OnFailureDrop OnFailureRetryStrategy = "drop" // Drop the operation and perform no further action. +) + +// RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. +// It includes a BackOff strategy to manage the timing of retries and defines the action to take upon failure. +type RetryStrategy struct { + // BackOff specifies the parameters for the backoff strategy, controlling how delays between retries should increase. + // +optional + BackOff *Backoff `json:"backoff,omitempty" protobuf:"bytes,1,opt,name=backoff"` + // OnFailure specifies the action to take when a retry fails. The default action is to retry. + // +optional + // +kubebuilder:default="retry" + OnFailure *OnFailureRetryStrategy `json:"onFailure,omitempty" protobuf:"bytes,2,opt,name=onFailure"` +} + +// Backoff defines parameters used to systematically configure the retry strategy. +type Backoff struct { + // Interval sets the delay to wait before retry, after a failure occurs. + // +kubebuilder:default="1ms" + // +optional + Interval *metav1.Duration `json:"interval,omitempty" protobuf:"bytes,1,opt,name=interval"` + // Steps defines the number of times to try writing to a sink including retries + // +optional + Steps *uint32 `json:"steps,omitempty" protobuf:"bytes,2,opt,name=steps"` + // TODO(Retry): Enable after we add support for exponential backoff + //// +optional + //Cap *metav1.Duration `json:"cap,omitempty" protobuf:"bytes,3,opt,name=cap"` + //// +optional + //Factor *floatstr `json:"factor,omitempty" protobuf:"bytes,2,opt,name=factor"` + //// +optional + //Jitter *floatstr `json:"jitter,omitempty" protobuf:"bytes,3,opt,name=jitter"` +} + +// GetBackoff constructs a wait.Backoff configuration using default values and optionally overrides +// these defaults with custom settings specified in the RetryStrategy. +func (r RetryStrategy) GetBackoff() wait.Backoff { + // Initialize the Backoff structure with default values. + wt := wait.Backoff{ + Duration: DefaultRetryInterval, + Steps: DefaultRetrySteps, + } + + // If a custom back-off configuration is present, check and substitute the respective parts. + if r.BackOff != nil { + // If a custom Interval is specified, override the default Duration. + if r.BackOff.Interval != nil { + wt.Duration = r.BackOff.Interval.Duration + } + // If custom Steps are specified, override the default Steps. + if r.BackOff.Steps != nil { + wt.Steps = int(*r.BackOff.Steps) + } + } + + // Returns the fully configured Backoff structure, which is either default or overridden by custom settings. + return wt +} + +// GetOnFailureRetryStrategy retrieves the currently set strategy for handling failures upon retrying. +// This method uses a default strategy which can be overridden by a custom strategy defined in RetryStrategy. +func (r RetryStrategy) GetOnFailureRetryStrategy() OnFailureRetryStrategy { + // If the OnFailure is not defined initialize with the Default value + if r.OnFailure == nil { + return DefaultOnFailureRetryStrategy + } + switch *r.OnFailure { + case OnFailureRetry, OnFailureFallback, OnFailureDrop: + // If a custom on-failure behavior is specified + return *r.OnFailure + default: + return DefaultOnFailureRetryStrategy + } +} diff --git a/pkg/apis/numaflow/v1alpha1/retry_strategy_test.go b/pkg/apis/numaflow/v1alpha1/retry_strategy_test.go new file mode 100644 index 0000000000..e8968b9d36 --- /dev/null +++ b/pkg/apis/numaflow/v1alpha1/retry_strategy_test.go @@ -0,0 +1,115 @@ +/* +Copyright 2022 The Numaproj Authors. + +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 v1alpha1 + +import ( + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +func TestGetBackoff(t *testing.T) { + steps := uint32(10) + tests := []struct { + name string + strategy RetryStrategy + expectedBackoff wait.Backoff + steps uint32 + }{ + { + name: "default backoff", + strategy: RetryStrategy{}, + expectedBackoff: wait.Backoff{ + Duration: DefaultRetryInterval, + Steps: DefaultRetrySteps, + }, + }, + { + name: "custom backoff", + strategy: RetryStrategy{ + BackOff: &Backoff{ + Interval: &metav1.Duration{Duration: 10 * time.Second}, + Steps: &steps, + }, + }, + expectedBackoff: wait.Backoff{ + Duration: 10 * time.Second, + Steps: 10, + }, + }, + { + name: "custom backoff - 2", + strategy: RetryStrategy{ + BackOff: &Backoff{ + Interval: &metav1.Duration{Duration: 10 * time.Second}, + }, + }, + expectedBackoff: wait.Backoff{ + Duration: 10 * time.Second, + Steps: DefaultRetrySteps, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.strategy.GetBackoff() + if got.Duration != tt.expectedBackoff.Duration || got.Steps != tt.expectedBackoff.Steps { + t.Errorf("GetBackoff() = %v, want %v", got, tt.expectedBackoff) + } + }) + } +} + +func TestGetOnFailureRetryStrategy(t *testing.T) { + tests := []struct { + name string + strategy RetryStrategy + expectedOnFailure OnFailureRetryStrategy + }{ + { + name: "default strategy", + strategy: RetryStrategy{}, + expectedOnFailure: DefaultOnFailureRetryStrategy, + }, + { + name: "custom strategy", + strategy: RetryStrategy{ + OnFailure: func() *OnFailureRetryStrategy { s := OnFailureDrop; return &s }(), + }, + expectedOnFailure: OnFailureDrop, + }, + { + name: "incorrect strategy - use default", + strategy: RetryStrategy{ + OnFailure: func() *OnFailureRetryStrategy { s := "xxxx"; return (*OnFailureRetryStrategy)(&s) }(), + }, + expectedOnFailure: DefaultOnFailureRetryStrategy, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.strategy.GetOnFailureRetryStrategy() + if got != tt.expectedOnFailure { + t.Errorf("GetOnFailureRetryStrategy() = %v, want %v", got, tt.expectedOnFailure) + } + }) + } +} diff --git a/pkg/apis/numaflow/v1alpha1/sink.go b/pkg/apis/numaflow/v1alpha1/sink.go index 8530259214..d596a079e6 100644 --- a/pkg/apis/numaflow/v1alpha1/sink.go +++ b/pkg/apis/numaflow/v1alpha1/sink.go @@ -27,6 +27,9 @@ type Sink struct { // initiated if the ud-sink response field sets it. // +optional Fallback *AbstractSink `json:"fallback,omitempty" protobuf:"bytes,2,opt,name=fallback"` + // RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. + // +optional + RetryStrategy RetryStrategy `json:"retryStrategy,omitempty" protobuf:"bytes,3,opt,name=retryStrategy"` } type AbstractSink struct { diff --git a/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go index a5ee6d9b6f..6033c0302f 100644 --- a/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go @@ -245,6 +245,32 @@ func (in *Authorization) DeepCopy() *Authorization { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Backoff) DeepCopyInto(out *Backoff) { + *out = *in + if in.Interval != nil { + in, out := &in.Interval, &out.Interval + *out = new(metav1.Duration) + **out = **in + } + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = new(uint32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backoff. +func (in *Backoff) DeepCopy() *Backoff { + if in == nil { + return nil + } + out := new(Backoff) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BasicAuth) DeepCopyInto(out *BasicAuth) { *out = *in @@ -1957,6 +1983,32 @@ func (in *RedisSettings) DeepCopy() *RedisSettings { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RetryStrategy) DeepCopyInto(out *RetryStrategy) { + *out = *in + if in.BackOff != nil { + in, out := &in.BackOff, &out.BackOff + *out = new(Backoff) + (*in).DeepCopyInto(*out) + } + if in.OnFailure != nil { + in, out := &in.OnFailure, &out.OnFailure + *out = new(OnFailureRetryStrategy) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetryStrategy. +func (in *RetryStrategy) DeepCopy() *RetryStrategy { + if in == nil { + return nil + } + out := new(RetryStrategy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SASL) DeepCopyInto(out *SASL) { *out = *in @@ -2263,6 +2315,7 @@ func (in *Sink) DeepCopyInto(out *Sink) { *out = new(AbstractSink) (*in).DeepCopyInto(*out) } + in.RetryStrategy.DeepCopyInto(&out.RetryStrategy) return } diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index f4e394004e..95ce17b984 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -86,7 +86,7 @@ var ( Help: "Total number of bytes written", }, []string{LabelVertex, LabelPipeline, LabelVertexType, LabelVertexReplicaIndex, LabelPartitionName}) - // WriteMessagesError is used to indicate the number of errors messages written + // WriteMessagesError is used to indicate the number of errors encountered while writing messages WriteMessagesError = promauto.NewCounterVec(prometheus.CounterOpts{ Subsystem: "forwarder", Name: "write_error_total", @@ -298,3 +298,27 @@ var ( Help: "Total number of ctrl Messages sent", }, []string{LabelVertex, LabelPipeline, LabelVertexType, LabelVertexReplicaIndex, LabelPartitionName}) ) + +// Sink forwarder metrics +var ( + // FbSinkWriteMessagesCount is used to indicate the number of messages written to a fallback sink + FbSinkWriteMessagesCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Subsystem: "forwarder", + Name: "fbsink_write_total", + Help: "Total number of Messages written to a fallback sink", + }, []string{LabelVertex, LabelPipeline, LabelVertexType, LabelVertexReplicaIndex, LabelPartitionName}) + + // FbSinkWriteBytesCount is to indicate the number of bytes written to a fallback sink + FbSinkWriteBytesCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Subsystem: "forwarder", + Name: "fbsink_write_bytes_total", + Help: "Total number of bytes written to a fallback sink", + }, []string{LabelVertex, LabelPipeline, LabelVertexType, LabelVertexReplicaIndex, LabelPartitionName}) + + // FbSinkWriteMessagesError is used to indicate the number of errors while writing to a fallback sink + FbSinkWriteMessagesError = promauto.NewCounterVec(prometheus.CounterOpts{ + Subsystem: "forwarder", + Name: "fbsink_write_error_total", + Help: "Total number of Write Errors while writing to a fallback sink", + }, []string{LabelVertex, LabelPipeline, LabelVertexType, LabelVertexReplicaIndex, LabelPartitionName}) +) diff --git a/pkg/reconciler/pipeline/validate.go b/pkg/reconciler/pipeline/validate.go index 0fc443b6b5..2a98c2e665 100644 --- a/pkg/reconciler/pipeline/validate.go +++ b/pkg/reconciler/pipeline/validate.go @@ -272,6 +272,10 @@ func validateVertex(v dfv1.AbstractVertex) error { if v.UDF != nil { return validateUDF(*v.UDF) } + + if v.Sink != nil { + return validateSink(*v.Sink) + } return nil } @@ -553,3 +557,33 @@ func buildVisitedMap(vtxName string, visited map[string]struct{}, pl *dfv1.Pipel } } + +// validateSink initiates the validation of the sink spec for a pipeline +func validateSink(sink dfv1.Sink) error { + // check the sinks retry strategy validity. + if ok := HasValidSinkRetryStrategy(sink); !ok { + return fmt.Errorf("given OnFailure strategy is fallback but fallback sink is not provided") + } + return nil +} + +// HasValidSinkRetryStrategy checks if the provided RetryStrategy is valid based on the sink's configuration. +// This validation ensures that the retry strategy is compatible with the sink's current setup +func HasValidSinkRetryStrategy(s dfv1.Sink) bool { + // If the OnFailure strategy is set to fallback, but no fallback sink is provided in the Sink struct, + // we return an error + if s.RetryStrategy.OnFailure != nil && *s.RetryStrategy.OnFailure == dfv1.OnFailureFallback && !hasValidFallbackSink(&s) { + return false + } + // If steps are provided in the strategy they cannot be 0, as we do not allow no tries for writing + if s.RetryStrategy.BackOff != nil && s.RetryStrategy.BackOff.Steps != nil && *s.RetryStrategy.BackOff.Steps == 0 { + return false + } + // If no errors are found, the function returns true indicating the validation passed. + return true +} + +// HasValidFallbackSink checks if the Sink vertex has a valid fallback sink configured +func hasValidFallbackSink(s *dfv1.Sink) bool { + return s.Fallback != nil && s.Fallback.UDSink != nil +} diff --git a/pkg/reconciler/pipeline/validate_test.go b/pkg/reconciler/pipeline/validate_test.go index 486b36c9be..f116e04825 100644 --- a/pkg/reconciler/pipeline/validate_test.go +++ b/pkg/reconciler/pipeline/validate_test.go @@ -1056,3 +1056,125 @@ func Test_validateIdleSource(t *testing.T) { assert.Error(t, err) assert.Contains(t, err.Error(), `invalid idle source watermark config, threshold should be greater than or equal to incrementBy`) } + +// TestValidateSink tests the validateSink function with different sink configurations. +func TestValidateSink(t *testing.T) { + onFailFallback := dfv1.OnFailureFallback + tests := []struct { + name string + sink dfv1.Sink + expectedError bool + }{ + { + name: "Valid configuration without needing fallback", + sink: dfv1.Sink{ + RetryStrategy: dfv1.RetryStrategy{OnFailure: nil}, + }, + expectedError: false, + }, + { + name: "Valid configuration with valid fallback", + sink: dfv1.Sink{ + RetryStrategy: dfv1.RetryStrategy{OnFailure: &onFailFallback}, + // represents a valid fallback sink + Fallback: &dfv1.AbstractSink{ + UDSink: &dfv1.UDSink{}, + }, + }, + expectedError: false, + }, + { + name: "Valid configuration with invalid fallback - no UDSink", + sink: dfv1.Sink{ + RetryStrategy: dfv1.RetryStrategy{OnFailure: &onFailFallback}, + Fallback: &dfv1.AbstractSink{}, // represents a valid fallback sink + }, + expectedError: true, + }, + { + name: "Invalid configuration, fallback needed but not provided", + sink: dfv1.Sink{ + RetryStrategy: dfv1.RetryStrategy{OnFailure: &onFailFallback}, + Fallback: nil, + }, + expectedError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Run the validation function + err := validateSink(tt.sink) + // Check if an error was expected or not + if (err != nil) != tt.expectedError { + t.Errorf("%s: validateSink() error = %v, wantErr %v", tt.name, err, tt.expectedError) + } + }) + } +} + +func TestIsValidSinkRetryStrategy(t *testing.T) { + zeroSteps := uint32(0) + tests := []struct { + name string + sink dfv1.Sink + strategy dfv1.RetryStrategy + wantErr bool + }{ + { + name: "valid strategy with fallback configured", + sink: dfv1.Sink{Fallback: &dfv1.AbstractSink{ + UDSink: &dfv1.UDSink{}, + }}, + strategy: dfv1.RetryStrategy{ + OnFailure: func() *dfv1.OnFailureRetryStrategy { str := dfv1.OnFailureFallback; return &str }(), + }, + wantErr: false, + }, + { + name: "invalid valid strategy with fallback not configured properly", + sink: dfv1.Sink{Fallback: &dfv1.AbstractSink{}}, + strategy: dfv1.RetryStrategy{ + OnFailure: func() *dfv1.OnFailureRetryStrategy { str := dfv1.OnFailureFallback; return &str }(), + }, + wantErr: true, + }, + { + name: "invalid strategy with no fallback configured", + sink: dfv1.Sink{}, + strategy: dfv1.RetryStrategy{ + OnFailure: func() *dfv1.OnFailureRetryStrategy { str := dfv1.OnFailureFallback; return &str }(), + }, + wantErr: true, + }, + { + name: "valid strategy with drop and no fallback needed", + sink: dfv1.Sink{}, + strategy: dfv1.RetryStrategy{ + OnFailure: func() *dfv1.OnFailureRetryStrategy { str := dfv1.OnFailureDrop; return &str }(), + }, + wantErr: false, + }, + { + name: "invalid strategy with 0 steps", + sink: dfv1.Sink{}, + strategy: dfv1.RetryStrategy{ + BackOff: &dfv1.Backoff{ + Steps: &zeroSteps, + }, + OnFailure: func() *dfv1.OnFailureRetryStrategy { str := dfv1.OnFailureDrop; return &str }(), + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.sink.RetryStrategy = tt.strategy + ok := HasValidSinkRetryStrategy(tt.sink) + if (!ok) != tt.wantErr { + t.Errorf("isValidSinkRetryStrategy() got = %v, want %v", ok, tt.wantErr) + } + }) + } +} diff --git a/pkg/sinks/forward/forward.go b/pkg/sinks/forward/forward.go index acddb40567..ad53b5fa51 100644 --- a/pkg/sinks/forward/forward.go +++ b/pkg/sinks/forward/forward.go @@ -54,6 +54,7 @@ type DataForward struct { vertexName string pipelineName string vertexReplica int32 + sinkRetryStrategy dfv1.RetryStrategy // idleManager manages the idle watermark status. idleManager wmb.IdleManager // wmbChecker checks if the idle watermark is valid. @@ -98,6 +99,10 @@ func NewDataForward( }, opts: *dOpts, } + // add the sink retry strategy to the forward + if vertexInstance.Vertex.Spec.Sink != nil { + df.sinkRetryStrategy = vertexInstance.Vertex.Spec.Sink.RetryStrategy + } // Add logger from parent ctx to child context. df.ctx = logging.WithLogger(ctx, dOpts.logger) @@ -357,82 +362,184 @@ func (df *DataForward) ackFromBuffer(ctx context.Context, offsets []isb.Offset) return ctxClosedErr } -// writeToSink forwards an array of messages to a sink and it is a blocking call it keeps retrying until shutdown has been initiated. -func (df *DataForward) writeToSink(ctx context.Context, sinkWriter sinker.SinkWriter, messages []isb.Message, isFbSinkWriter bool) ([]isb.Offset, []isb.Message, error) { +// writeToSink forwards an array of messages to a sink and it is a blocking call it keeps retrying +// until shutdown has been initiated. The function also evaluates whether to use a fallback sink based +// on the error and configuration. +func (df *DataForward) writeToSink(ctx context.Context, sinkWriter sinker.SinkWriter, messagesToTry []isb.Message, isFbSinkWriter bool) ([]isb.Offset, []isb.Message, error) { var ( - err error - writeCount int - writeBytes float64 + err error + writeCount int + writeBytes float64 + fallbackMessages []isb.Message ) - writeOffsets := make([]isb.Offset, 0, len(messages)) - var fallbackMessages []isb.Message + // slice to store the successful offsets returned by the sink + writeOffsets := make([]isb.Offset, 0, len(messagesToTry)) + + // extract the backOff conditions and failStrategy for the retry logic, + // when the isFbSinkWriter is true, we use an infinite retry + backoffCond, failStrategy := df.getBackOffConditions(isFbSinkWriter) + // The loop will continue trying to write messages until they are all processed + // or an unrecoverable error occurs. for { - _writeOffsets, errs := sinkWriter.Write(ctx, messages) - // Note: this is an unwanted memory allocation during a happy path. We want only minimal allocation since using failedMessages is an unlikely path. - var failedMessages []isb.Message - needRetry := false - for idx, msg := range messages { - - if err = errs[idx]; err != nil { - // if we are asked to write to fallback sink, check if the fallback sink is configured, - // and we are not already in the fallback sink write path. - if errors.Is(err, &udsink.WriteToFallbackErr) && df.opts.fbSinkWriter != nil && !isFbSinkWriter { - fallbackMessages = append(fallbackMessages, msg) - continue - } + err = wait.ExponentialBackoffWithContext(ctx, backoffCond, func(_ context.Context) (done bool, err error) { + // Note: this is an unwanted memory allocation during a happy path. We want only minimal allocation + // since using failedMessages is an unlikely path. + var failedMessages []isb.Message + needRetry := false + _writeOffsets, errs := sinkWriter.Write(ctx, messagesToTry) + for idx, msg := range messagesToTry { + if err = errs[idx]; err != nil { + // if we are asked to write to fallback sink, check if the fallback sink is configured, + // and we are not already in the fallback sink write path. + if errors.Is(err, &udsink.WriteToFallbackErr) && df.opts.fbSinkWriter != nil && !isFbSinkWriter { + fallbackMessages = append(fallbackMessages, msg) + continue + } - // if we are asked to write to fallback but no fallback sink is configured, we will retry the messages to the same sink - if errors.Is(err, &udsink.WriteToFallbackErr) && df.opts.fbSinkWriter == nil { - df.opts.logger.Error("Asked to write to fallback but no fallback sink is configured, retrying the message to the same sink") - } + // if we are asked to write to fallback but no fallback sink is configured, we will retry the messages to the same sink + if errors.Is(err, &udsink.WriteToFallbackErr) && df.opts.fbSinkWriter == nil { + df.opts.logger.Error("Asked to write to fallback but no fallback sink is configured, retrying the message to the same sink") + } - // if we are asked to write to fallback sink inside the fallback sink, we will retry the messages to the fallback sink - if errors.Is(err, &udsink.WriteToFallbackErr) && isFbSinkWriter { - df.opts.logger.Error("Asked to write to fallback sink inside the fallback sink, retrying the message to fallback sink") - } + // if we are asked to write to fallback sink inside the fallback sink, we will retry the messages to the fallback sink + if errors.Is(err, &udsink.WriteToFallbackErr) && isFbSinkWriter { + df.opts.logger.Error("Asked to write to fallback sink inside the fallback sink, retrying the message to fallback sink") + } - needRetry = true - // we retry only failed messages - failedMessages = append(failedMessages, msg) - metrics.WriteMessagesError.With(map[string]string{metrics.LabelVertex: df.vertexName, metrics.LabelPipeline: df.pipelineName, metrics.LabelVertexType: string(dfv1.VertexTypeSink), metrics.LabelVertexReplicaIndex: strconv.Itoa(int(df.vertexReplica)), metrics.LabelPartitionName: sinkWriter.GetName()}).Inc() - // a shutdown can break the blocking loop caused due to InternalErr - if ok, _ := df.IsShuttingDown(); ok { - metrics.PlatformError.With(map[string]string{metrics.LabelVertex: df.vertexName, metrics.LabelPipeline: df.pipelineName, metrics.LabelVertexType: string(dfv1.VertexTypeSink), metrics.LabelVertexReplicaIndex: strconv.Itoa(int(df.vertexReplica))}).Inc() - return nil, nil, fmt.Errorf("writeToSink failed, Stop called while stuck on an internal error with failed messages:%d, %v", len(failedMessages), errs) - } - } else { - writeCount++ - writeBytes += float64(len(msg.Payload)) - // we support write offsets only for jetstream - if _writeOffsets != nil { - writeOffsets = append(writeOffsets, _writeOffsets[idx]) + needRetry = true + + // TODO(Retry-Sink) : Propagate the retry-count? + // we retry only failed message + failedMessages = append(failedMessages, msg) + + // increment the error metric + df.incrementErrorMetric(sinkWriter.GetName(), isFbSinkWriter) + + // a shutdown can break the blocking loop caused due to InternalErr + if ok, _ := df.IsShuttingDown(); ok { + metrics.PlatformError.With(map[string]string{metrics.LabelVertex: df.vertexName, metrics.LabelPipeline: df.pipelineName, metrics.LabelVertexType: string(dfv1.VertexTypeSink), metrics.LabelVertexReplicaIndex: strconv.Itoa(int(df.vertexReplica))}).Inc() + return true, fmt.Errorf("writeToSink failed, Stop called while stuck on an internal error with failed messages:%d, %v", len(failedMessages), errs) + } + } else { + writeCount++ + writeBytes += float64(len(msg.Payload)) + // we support write offsets only for jetstream + if _writeOffsets != nil { + writeOffsets = append(writeOffsets, _writeOffsets[idx]) + } } } + // set messages to failedMessages, in case of success this should be empty + // While checking for retry we see the length of the messages left + messagesToTry = failedMessages + if needRetry { + df.opts.logger.Errorw("Retrying failed messages", + zap.Any("errors", errorArrayToMap(errs)), + zap.String(metrics.LabelPipeline, df.pipelineName), + zap.String(metrics.LabelVertex, df.vertexName), + zap.String(metrics.LabelPartitionName, sinkWriter.GetName()), + ) + return false, nil + } + return true, nil + }) + // If we exited out of the loop and it was due to a forced shutdown we should exit + // TODO(Retry-Sink): Check for ctx done separately? That should be covered in shutdown + if ok, _ := df.IsShuttingDown(); err != nil && ok { + return nil, nil, err } - - if needRetry { - df.opts.logger.Errorw("Retrying failed messages", - zap.Any("errors", errorArrayToMap(errs)), - zap.String(metrics.LabelPipeline, df.pipelineName), - zap.String(metrics.LabelVertex, df.vertexName), - zap.String(metrics.LabelPartitionName, sinkWriter.GetName()), - ) - // set messages to failed for the retry - messages = failedMessages - // TODO: implement retry with backoff etc. - time.Sleep(df.opts.retryInterval) - } else { + // Check what actions are required once the writing loop is completed + // Break if no further action is required + if !df.handlePostRetryFailures(&messagesToTry, failStrategy, &fallbackMessages, sinkWriter) { break } } - - metrics.WriteMessagesCount.With(map[string]string{metrics.LabelVertex: df.vertexName, metrics.LabelPipeline: df.pipelineName, metrics.LabelVertexType: string(dfv1.VertexTypeSink), metrics.LabelVertexReplicaIndex: strconv.Itoa(int(df.vertexReplica)), metrics.LabelPartitionName: sinkWriter.GetName()}).Add(float64(writeCount)) - metrics.WriteBytesCount.With(map[string]string{metrics.LabelVertex: df.vertexName, metrics.LabelPipeline: df.pipelineName, metrics.LabelVertexType: string(dfv1.VertexTypeSink), metrics.LabelVertexReplicaIndex: strconv.Itoa(int(df.vertexReplica)), metrics.LabelPartitionName: sinkWriter.GetName()}).Add(writeBytes) + // update the write metrics for sink + df.updateSinkWriteMetrics(writeCount, writeBytes, sinkWriter.GetName(), isFbSinkWriter) return writeOffsets, fallbackMessages, nil } +// handlePostRetryFailures deals with the scenarios after retries are exhausted. +// It returns true if we need to continue retrying else returns false when no further writes are required +func (df *DataForward) handlePostRetryFailures(messagesToTry *[]isb.Message, failStrategy dfv1.OnFailureRetryStrategy, fallbackMessages *[]isb.Message, + sinkWriter sinker.SinkWriter) bool { + + // Check if we still have messages left to be processed + if len(*messagesToTry) > 0 { + + df.opts.logger.Infof("Retries exhausted in sink, messagesLeft %d, Next strategy %s", + len(*messagesToTry), failStrategy) + + // Check what is the failure strategy to be followed after retry exhaustion + switch failStrategy { + case dfv1.OnFailureRetry: + // If on failure, we keep on retrying then lets continue the loop and try all again + return true + case dfv1.OnFailureFallback: + // If onFail we have to divert messages to fallback, lets add all failed messages to fallback slice + *fallbackMessages = append(*fallbackMessages, *messagesToTry...) + case dfv1.OnFailureDrop: + // If on fail we want to Drop in that case lets not retry further + df.opts.logger.Info("Dropping the failed messages after retry in the Sink") + // Update the drop metric count with the messages left + metrics.DropMessagesCount.With(map[string]string{ + metrics.LabelVertex: df.vertexName, + metrics.LabelPipeline: df.pipelineName, + metrics.LabelVertexType: string(dfv1.VertexTypeSink), + metrics.LabelVertexReplicaIndex: strconv.Itoa(int(df.vertexReplica)), + metrics.LabelPartitionName: sinkWriter.GetName(), + metrics.LabelReason: "retries exhausted in the Sink", + }).Add(float64(len(*messagesToTry))) + } + } + return false +} + +// updateSinkWriteMetrics updates metrics related to data writes to a sink. +// Metrics are updated based on whether the operation involves the primary or fallback sink. +func (df *DataForward) updateSinkWriteMetrics(writeCount int, writeBytes float64, sinkWriterName string, isFallback bool) { + // Define labels to keep track of the data related to the specific operation + labels := map[string]string{ + metrics.LabelVertex: df.vertexName, + metrics.LabelPipeline: df.pipelineName, + metrics.LabelVertexType: string(dfv1.VertexTypeSink), + metrics.LabelVertexReplicaIndex: strconv.Itoa(int(df.vertexReplica)), + metrics.LabelPartitionName: sinkWriterName, + } + + // Increment the metrics for message count and bytes + metrics.WriteMessagesCount.With(labels).Add(float64(writeCount)) + metrics.WriteBytesCount.With(labels).Add(writeBytes) + + // if this is for Fallback Sink, increment specific metrics as well + if isFallback { + metrics.FbSinkWriteMessagesCount.With(labels).Add(float64(writeCount)) + metrics.FbSinkWriteBytesCount.With(labels).Add(writeBytes) + } +} + +// incrementErrorMetric updates the appropriate error metric based on whether the operation involves a fallback sink. +func (df *DataForward) incrementErrorMetric(sinkWriter string, isFbSinkWriter bool) { + // Define labels to keep track of the data related to the specific operation + labels := map[string]string{ + metrics.LabelVertex: df.vertexName, + metrics.LabelPipeline: df.pipelineName, + metrics.LabelVertexType: string(dfv1.VertexTypeSink), + metrics.LabelVertexReplicaIndex: strconv.Itoa(int(df.vertexReplica)), + metrics.LabelPartitionName: sinkWriter, + } + + // Increment the selected metric and attach labels to provide detailed context: + metrics.WriteMessagesError.With(labels).Inc() + + // Increment fallback specific metric if fallback mode + if isFbSinkWriter { + metrics.FbSinkWriteMessagesError.With(labels).Inc() + } +} + // errorArrayToMap summarizes an error array to map func errorArrayToMap(errs []error) map[string]int64 { result := make(map[string]int64) @@ -443,3 +550,16 @@ func errorArrayToMap(errs []error) map[string]int64 { } return result } + +// getBackOffConditions configures the retry backoff strategy based on whether its a fallbackSink or primary sink. +func (df *DataForward) getBackOffConditions(isFallbackSink bool) (wait.Backoff, dfv1.OnFailureRetryStrategy) { + // If we want for isFallbackSink we will return an infinite retry which will keep retrying post exhaustion till it succeeds + if isFallbackSink { + return wait.Backoff{ + Duration: dfv1.DefaultRetryInterval, + Steps: dfv1.DefaultRetrySteps, + }, dfv1.OnFailureRetry + } + // Initial interval duration and number of retries are taken from DataForward settings. + return df.sinkRetryStrategy.GetBackoff(), df.sinkRetryStrategy.GetOnFailureRetryStrategy() +} diff --git a/pkg/sinks/forward/options.go b/pkg/sinks/forward/options.go index f18dbe2620..afb6d1f37b 100644 --- a/pkg/sinks/forward/options.go +++ b/pkg/sinks/forward/options.go @@ -17,8 +17,6 @@ limitations under the License. package forward import ( - "time" - "go.uber.org/zap" dfv1 "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1" @@ -33,8 +31,6 @@ type options struct { readBatchSize int64 // sinkConcurrency sets the concurrency for concurrent processing sinkConcurrency int - // retryInterval is the time.Duration to sleep before retrying - retryInterval time.Duration // fbSinkWriter is the writer for the fallback sink fbSinkWriter sinker.SinkWriter // logger is used to pass the logger variable @@ -49,7 +45,6 @@ func DefaultOptions() *options { return &options{ readBatchSize: dfv1.DefaultReadBatchSize, sinkConcurrency: dfv1.DefaultReadBatchSize, - retryInterval: time.Millisecond, logger: logging.NewLogger(), } } @@ -70,14 +65,6 @@ func WithSinkConcurrency(f int) Option { } } -// WithRetryInterval sets the retry interval -func WithRetryInterval(f time.Duration) Option { - return func(o *options) error { - o.retryInterval = time.Duration(f) - return nil - } -} - // WithLogger is used to return logger information func WithLogger(l *zap.SugaredLogger) Option { return func(o *options) error { diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 4e3ba1085b..6b34934210 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1473,6 +1473,7 @@ dependencies = [ "bytes", "chrono", "hyper-util", + "kube", "numaflow 0.1.0 (git+https://github.com/numaproj/numaflow-rs.git?branch=main)", "numaflow-models", "once_cell", diff --git a/rust/monovertex/Cargo.toml b/rust/monovertex/Cargo.toml index 00c51e6e9a..90ddc5cbec 100644 --- a/rust/monovertex/Cargo.toml +++ b/rust/monovertex/Cargo.toml @@ -33,6 +33,7 @@ pep440_rs = "0.6.6" backoff = { path = "../backoff" } parking_lot = "0.12.3" prometheus-client = "0.22.3" +kube = "0.93.1" [dev-dependencies] tempfile = "3.11.0" diff --git a/rust/monovertex/src/config.rs b/rust/monovertex/src/config.rs index 00f966b9bc..d1450500be 100644 --- a/rust/monovertex/src/config.rs +++ b/rust/monovertex/src/config.rs @@ -4,7 +4,7 @@ use std::sync::OnceLock; use base64::prelude::BASE64_STANDARD; use base64::Engine; -use numaflow_models::models::MonoVertex; +use numaflow_models::models::{Backoff, MonoVertex, RetryStrategy}; use crate::error::Error; @@ -17,8 +17,9 @@ const DEFAULT_LAG_CHECK_INTERVAL_IN_SECS: u16 = 5; const DEFAULT_LAG_REFRESH_INTERVAL_IN_SECS: u16 = 3; const DEFAULT_BATCH_SIZE: u64 = 500; const DEFAULT_TIMEOUT_IN_MS: u32 = 1000; -const DEFAULT_MAX_SINK_RETRY_ATTEMPTS: u16 = 10; +const DEFAULT_MAX_SINK_RETRY_ATTEMPTS: u16 = u16::MAX; const DEFAULT_SINK_RETRY_INTERVAL_IN_MS: u32 = 1; +const DEFAULT_SINK_RETRY_ON_FAIL_STRATEGY: &str = "retry"; pub fn config() -> &'static Settings { static CONF: OnceLock = OnceLock::new(); @@ -43,10 +44,22 @@ pub struct Settings { pub lag_refresh_interval_in_secs: u16, pub sink_max_retry_attempts: u16, pub sink_retry_interval_in_ms: u32, + pub sink_retry_on_fail_strategy: String, + pub sink_default_retry_strategy: RetryStrategy, } impl Default for Settings { fn default() -> Self { + // Create a default retry strategy from defined constants + let default_retry_strategy = RetryStrategy { + backoff: Option::from(Box::from(Backoff { + interval: Option::from(kube::core::Duration::from( + std::time::Duration::from_millis(DEFAULT_SINK_RETRY_INTERVAL_IN_MS as u64), + )), + steps: Option::from(DEFAULT_MAX_SINK_RETRY_ATTEMPTS as i64), + })), + on_failure: Option::from(DEFAULT_SINK_RETRY_ON_FAIL_STRATEGY.to_string()), + }; Self { mono_vertex_name: "default".to_string(), replica: 0, @@ -60,6 +73,8 @@ impl Default for Settings { lag_refresh_interval_in_secs: DEFAULT_LAG_REFRESH_INTERVAL_IN_SECS, sink_max_retry_attempts: DEFAULT_MAX_SINK_RETRY_ATTEMPTS, sink_retry_interval_in_ms: DEFAULT_SINK_RETRY_INTERVAL_IN_MS, + sink_retry_on_fail_strategy: DEFAULT_SINK_RETRY_ON_FAIL_STRATEGY.to_string(), + sink_default_retry_strategy: default_retry_strategy, } } } @@ -113,9 +128,56 @@ impl Settings { settings.is_fallback_enabled = mono_vertex_obj .spec .sink + .as_deref() .ok_or(Error::ConfigError("Sink not found".to_string()))? .fallback .is_some(); + + if let Some(retry_strategy) = mono_vertex_obj + .spec + .sink + .expect("sink should not be empty") + .retry_strategy + { + if let Some(sink_backoff) = retry_strategy.clone().backoff { + // Set the max retry attempts and retry interval using direct reference + settings.sink_retry_interval_in_ms = sink_backoff + .clone() + .interval + .map(|x| std::time::Duration::from(x).as_millis() as u32) + .unwrap_or(DEFAULT_SINK_RETRY_INTERVAL_IN_MS); + + settings.sink_max_retry_attempts = sink_backoff + .clone() + .steps + .map(|x| x as u16) + .unwrap_or(DEFAULT_MAX_SINK_RETRY_ATTEMPTS); + + // We do not allow 0 attempts to write to sink + if settings.sink_max_retry_attempts == 0 { + return Err(Error::ConfigError( + "Retry Strategy given with 0 retry attempts".to_string(), + )); + } + } + + // Set the retry strategy using a direct reference whenever possible + settings.sink_retry_on_fail_strategy = retry_strategy + .on_failure + .clone() + .unwrap_or_else(|| DEFAULT_SINK_RETRY_ON_FAIL_STRATEGY.to_string()); + + // check if the sink retry strategy is set to fallback and there is no fallback sink configured + // then we should return an error + if settings.sink_retry_on_fail_strategy == "fallback" + && !settings.is_fallback_enabled + { + return Err(Error::ConfigError( + "Retry Strategy given as fallback but Fallback sink not configured" + .to_string(), + )); + } + } } settings.grpc_max_message_size = env::var(ENV_GRPC_MAX_MESSAGE_SIZE) @@ -136,31 +198,213 @@ impl Settings { #[cfg(test)] mod tests { - use std::env; - use super::*; + use serde_json::json; + use std::env; #[test] - fn test_settings_load() { - // Set up environment variables - unsafe { - env::set_var(ENV_MONO_VERTEX_OBJ, "eyJtZXRhZGF0YSI6eyJuYW1lIjoic2ltcGxlLW1vbm8tdmVydGV4IiwibmFtZXNwYWNlIjoiZGVmYXVsdCIsImNyZWF0aW9uVGltZXN0YW1wIjpudWxsfSwic3BlYyI6eyJyZXBsaWNhcyI6MCwic291cmNlIjp7InRyYW5zZm9ybWVyIjp7ImNvbnRhaW5lciI6eyJpbWFnZSI6InF1YXkuaW8vbnVtYWlvL251bWFmbG93LXJzL21hcHQtZXZlbnQtdGltZS1maWx0ZXI6c3RhYmxlIiwicmVzb3VyY2VzIjp7fX0sImJ1aWx0aW4iOm51bGx9LCJ1ZHNvdXJjZSI6eyJjb250YWluZXIiOnsiaW1hZ2UiOiJkb2NrZXIuaW50dWl0LmNvbS9wZXJzb25hbC95aGwwMS9zaW1wbGUtc291cmNlOnN0YWJsZSIsInJlc291cmNlcyI6e319fX0sInNpbmsiOnsidWRzaW5rIjp7ImNvbnRhaW5lciI6eyJpbWFnZSI6ImRvY2tlci5pbnR1aXQuY29tL3BlcnNvbmFsL3lobDAxL2JsYWNraG9sZS1zaW5rOnN0YWJsZSIsInJlc291cmNlcyI6e319fX0sImxpbWl0cyI6eyJyZWFkQmF0Y2hTaXplIjo1MDAsInJlYWRUaW1lb3V0IjoiMXMifSwic2NhbGUiOnt9fSwic3RhdHVzIjp7InJlcGxpY2FzIjowLCJsYXN0VXBkYXRlZCI6bnVsbCwibGFzdFNjYWxlZEF0IjpudWxsfX0="); - env::set_var(ENV_GRPC_MAX_MESSAGE_SIZE, "128000000"); - }; + fn test_settings_load_combined() { + // Define all JSON test configurations in separate scopes to use them distinctively + { + let json_data = json!({ + "metadata": { + "name": "simple-mono-vertex", + "namespace": "default", + "creationTimestamp": null + }, + "spec": { + "replicas": 0, + "source": { + "transformer": { + "container": { + "image": "xxxxxxx", + "resources": {} + }, + "builtin": null + }, + "udsource": { + "container": { + "image": "xxxxxxx", + "resources": {} + } + } + }, + "sink": { + "udsink": { + "container": { + "image": "xxxxxx", + "resources": {} + } + } + }, + "limits": { + "readBatchSize": 500, + "readTimeout": "1s" + }, + "scale": {}, + "status": { + "replicas": 0, + "lastUpdated": null, + "lastScaledAt": null + } + } + }); + let json_str = json_data.to_string(); + let encoded_json = BASE64_STANDARD.encode(json_str); + env::set_var(ENV_MONO_VERTEX_OBJ, encoded_json); - // Load settings - let settings = Settings::load().unwrap(); + // Execute and verify + let settings = Settings::load().unwrap(); + assert_eq!(settings.mono_vertex_name, "simple-mono-vertex"); + env::remove_var(ENV_MONO_VERTEX_OBJ); + } - // Verify settings - assert_eq!(settings.mono_vertex_name, "simple-mono-vertex"); - assert_eq!(settings.batch_size, 500); - assert_eq!(settings.timeout_in_ms, 1000); - assert_eq!(settings.grpc_max_message_size, 128000000); + { + // Test Retry Strategy Load + let json_data = json!({ + "metadata": { + "name": "simple-mono-vertex", + "namespace": "default", + "creationTimestamp": null + }, + "spec": { + "replicas": 0, + "source": { + "udsource": { + "container": { + "image": "xxxxxxx", + "resources": {} + } + } + }, + "sink": { + "udsink": { + "container": { + "image": "xxxxxx", + "resources": {} + } + }, + "retryStrategy": { + "backoff": { + "interval": "1s", + "steps": 5 + }, + }, + }, + "limits": { + "readBatchSize": 500, + "readTimeout": "1s" + }, + } + }); + let json_str = json_data.to_string(); + let encoded_json = BASE64_STANDARD.encode(json_str); + env::set_var(ENV_MONO_VERTEX_OBJ, encoded_json); - // Clean up environment variables - unsafe { + // Execute and verify + let settings = Settings::load().unwrap(); + assert_eq!(settings.sink_retry_on_fail_strategy, "retry"); + assert_eq!(settings.sink_max_retry_attempts, 5); + assert_eq!(settings.sink_retry_interval_in_ms, 1000); env::remove_var(ENV_MONO_VERTEX_OBJ); - env::remove_var(ENV_GRPC_MAX_MESSAGE_SIZE); - }; + } + + { + // Test Error Case: Retry Strategy Fallback without Fallback Sink + let json_data = json!({ + "metadata": { + "name": "simple-mono-vertex", + "namespace": "default", + "creationTimestamp": null + }, + "spec": { + "replicas": 0, + "source": { + "udsource": { + "container": { + "image": "xxxxxxx", + "resources": {} + } + } + }, + "sink": { + "udsink": { + "container": { + "image": "xxxxxx", + "resources": {} + } + }, + "retryStrategy": { + "backoff": { + "interval": "1s", + "steps": 5 + }, + "onFailure": "fallback" + }, + }, + "limits": { + "readBatchSize": 500, + "readTimeout": "1s" + }, + } + }); + let json_str = json_data.to_string(); + let encoded_json = BASE64_STANDARD.encode(json_str); + env::set_var(ENV_MONO_VERTEX_OBJ, encoded_json); + + // Execute and verify + assert!(Settings::load().is_err()); + env::remove_var(ENV_MONO_VERTEX_OBJ); + } + + { + // Test Error Case: Retry Strategy with 0 Retry Attempts + let json_data = json!({ + "metadata": { + "name": "simple-mono-vertex", + "namespace": "default", + "creationTimestamp": null + }, + "spec": { + "replicas": 0, + "source": { + "udsource": { + "container": { + "image": "xxxxxxx", + "resources": {} + } + } + }, + "sink": { + "udsink": { + "container": { + "image": "xxxxxx", + "resources": {} + } + }, + "retryStrategy": { + "backoff": { + "interval": "1s", + "steps": 0 + }, + "onFailure": "retry" + }, + }, + "limits": { + "readBatchSize": 500, + "readTimeout": "1s" + }, + } + }); + let json_str = json_data.to_string(); + let encoded_json = BASE64_STANDARD.encode(json_str); + env::set_var(ENV_MONO_VERTEX_OBJ, encoded_json); + + // Execute and verify + assert!(Settings::load().is_err()); + env::remove_var(ENV_MONO_VERTEX_OBJ); + } + // General cleanup + env::remove_var(ENV_GRPC_MAX_MESSAGE_SIZE); } } diff --git a/rust/monovertex/src/forwarder.rs b/rust/monovertex/src/forwarder.rs index 8efe16c844..0f55268576 100644 --- a/rust/monovertex/src/forwarder.rs +++ b/rust/monovertex/src/forwarder.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use crate::config::config; use crate::error::{Error, Result}; use crate::message::{Message, Offset}; @@ -7,7 +9,6 @@ use crate::sink::{proto, SinkClient}; use crate::source::SourceClient; use crate::transformer::TransformerClient; use chrono::Utc; -use std::collections::HashMap; use tokio::task::JoinSet; use tokio::time::sleep; use tokio_util::sync::CancellationToken; @@ -222,67 +223,43 @@ impl Forwarder { // we will overwrite this vec with failed messages and will keep retrying. let mut messages_to_send = messages; - while attempts <= config().sink_max_retry_attempts { - let start_time = tokio::time::Instant::now(); - match self.sink_client.sink_fn(messages_to_send.clone()).await { - Ok(response) => { - debug!( - attempts = attempts, - "Sink latency - {}ms", - start_time.elapsed().as_millis() - ); - attempts += 1; - - // create a map of id to result, since there is no strict requirement - // for the udsink to return the results in the same order as the requests - let result_map: HashMap<_, _> = response - .results - .iter() - .map(|result| (result.id.clone(), result)) - .collect(); - - error_map.clear(); - // drain all the messages that were successfully written - // and keep only the failed messages to send again - // construct the error map for the failed messages - messages_to_send.retain(|msg| { - if let Some(result) = result_map.get(&msg.id) { - return if result.status == proto::Status::Success as i32 { - false - } else if result.status == proto::Status::Fallback as i32 { - fallback_msgs.push(msg.clone()); // add to fallback messages - false - } else { - *error_map.entry(result.err_msg.clone()).or_insert(0) += 1; - true - }; - } - false - }); - - // if all messages are successfully written, break the loop - if messages_to_send.is_empty() { - break; - } - - warn!( - "Retry attempt {} due to retryable error. Errors: {:?}", - attempts, error_map - ); - sleep(tokio::time::Duration::from_millis( - config().sink_retry_interval_in_ms as u64, - )) + // only breaks out of this loop based on the retry strategy unless all the messages have been written to sink + // successfully. + loop { + while attempts < config().sink_max_retry_attempts { + let status = self + .write_to_sink_once(&mut error_map, &mut fallback_msgs, &mut messages_to_send) .await; + match status { + Ok(true) => break, + Ok(false) => { + attempts += 1; + warn!( + "Retry attempt {} due to retryable error. Errors: {:?}", + attempts, error_map + ); + } + Err(e) => Err(e)?, } - Err(e) => return Err(e), } - } - if !messages_to_send.is_empty() { - return Err(Error::SinkError(format!( - "Failed to sink messages after {} attempts. Errors: {:?}", - attempts, error_map - ))); + // If after the retries we still have messages to process, handle the post retry failures + let need_retry = self.handle_sink_post_retry( + &mut attempts, + &mut error_map, + &mut fallback_msgs, + &mut messages_to_send, + ); + match need_retry { + // if we are done with the messages, break the loop + Ok(false) => break, + // if we need to retry, reset the attempts and error_map + Ok(true) => { + attempts = 0; + error_map.clear(); + } + Err(e) => Err(e)?, + } } // If there are fallback messages, write them to the fallback sink @@ -294,6 +271,9 @@ impl Forwarder { .sink_time .get_or_create(&self.common_labels) .observe(start_time_e2e.elapsed().as_micros() as f64); + + // update the metric for number of messages written to the sink + // this included primary and fallback sink forward_metrics() .sink_write_total .get_or_create(&self.common_labels) @@ -301,6 +281,122 @@ impl Forwarder { Ok(()) } + /// Handles the post retry failures based on the configured strategy, + /// returns true if we need to retry, else false. + fn handle_sink_post_retry( + &mut self, + attempts: &mut u16, + error_map: &mut HashMap, + fallback_msgs: &mut Vec, + messages_to_send: &mut Vec, + ) -> Result { + // if we are done with the messages, break the loop + if messages_to_send.is_empty() { + return Ok(false); + } + // check what is the failure strategy in the config + let strategy = config().sink_retry_on_fail_strategy.clone(); + match strategy.as_str() { + // if we need to retry, return true + "retry" => { + warn!( + "Using onFailure Retry, Retry attempts {} completed", + attempts + ); + return Ok(true); + } + // if we need to drop the messages, log and return false + "drop" => { + // log that we are dropping the messages as requested + warn!( + "Dropping messages after {} attempts. Errors: {:?}", + attempts, error_map + ); + // update the metrics + forward_metrics() + .dropped_total + .get_or_create(&self.common_labels) + .inc_by(messages_to_send.len() as u64); + } + // if we need to move the messages to the fallback, return false + "fallback" => { + // log that we are moving the messages to the fallback as requested + warn!( + "Moving messages to fallback after {} attempts. Errors: {:?}", + attempts, error_map + ); + // move the messages to the fallback messages + fallback_msgs.append(messages_to_send); + } + // if the strategy is invalid, return an error + _ => { + return Err(Error::SinkError(format!( + "Invalid sink retry on fail strategy: {}", + strategy + ))); + } + } + // if we are done with the messages, break the loop + Ok(false) + } + + /// Writes to sink once and will return true if successful, else false. Please note that it + /// mutates is incoming fields. + async fn write_to_sink_once( + &mut self, + error_map: &mut HashMap, + fallback_msgs: &mut Vec, + messages_to_send: &mut Vec, + ) -> Result { + let start_time = tokio::time::Instant::now(); + match self.sink_client.sink_fn(messages_to_send.clone()).await { + Ok(response) => { + debug!("Sink latency - {}ms", start_time.elapsed().as_millis()); + + // create a map of id to result, since there is no strict requirement + // for the udsink to return the results in the same order as the requests + let result_map: HashMap<_, _> = response + .results + .iter() + .map(|result| (result.id.clone(), result)) + .collect(); + + error_map.clear(); + // drain all the messages that were successfully written + // and keep only the failed messages to send again + // construct the error map for the failed messages + messages_to_send.retain(|msg| { + if let Some(result) = result_map.get(&msg.id) { + return if result.status == proto::Status::Success as i32 { + false + } else if result.status == proto::Status::Fallback as i32 { + fallback_msgs.push(msg.clone()); // add to fallback messages + false + } else { + *error_map.entry(result.err_msg.clone()).or_insert(0) += 1; + true + }; + } + false + }); + + // if all messages are successfully written, break the loop + if messages_to_send.is_empty() { + return Ok(true); + } + + sleep(tokio::time::Duration::from_millis( + config().sink_retry_interval_in_ms as u64, + )) + .await; + + // we need to retry + return Ok(false); + } + Err(e) => return Err(e), + } + } + // Writes the fallback messages to the fallback sink async fn handle_fallback_messages(&mut self, fallback_msgs: Vec) -> Result<()> { if self.fallback_client.is_none() { @@ -316,8 +412,17 @@ impl Forwarder { // start with the original set of message to be sent. // we will overwrite this vec with failed messages and will keep retrying. let mut messages_to_send = fallback_msgs; + let fb_msg_count = messages_to_send.len() as u64; + + let default_retry = config() + .sink_default_retry_strategy + .clone() + .backoff + .unwrap(); + let max_attempts = default_retry.steps.unwrap(); + let sleep_interval = default_retry.interval.unwrap(); - while attempts <= config().sink_max_retry_attempts { + while attempts < max_attempts { let start_time = tokio::time::Instant::now(); match fallback_client.sink_fn(messages_to_send.clone()).await { Ok(fb_response) => { @@ -375,22 +480,22 @@ impl Forwarder { "Retry attempt {} due to retryable error. Errors: {:?}", attempts, fallback_error_map ); - sleep(tokio::time::Duration::from_millis( - config().sink_retry_interval_in_ms as u64, - )) - .await; + sleep(tokio::time::Duration::from(sleep_interval)).await; } Err(e) => return Err(e), } } - if !messages_to_send.is_empty() { return Err(Error::SinkError(format!( "Failed to write messages to fallback sink after {} attempts. Errors: {:?}", attempts, fallback_error_map ))); } - + // increment the metric for the fallback sink write + forward_metrics() + .fbsink_write_total + .get_or_create(&self.common_labels) + .inc_by(fb_msg_count); Ok(()) } @@ -420,17 +525,18 @@ impl Forwarder { mod tests { use std::collections::HashSet; - use crate::error::Result; - use crate::forwarder::ForwarderBuilder; - use crate::sink::{SinkClient, SinkConfig}; - use crate::source::{SourceClient, SourceConfig}; - use crate::transformer::{TransformerClient, TransformerConfig}; use chrono::Utc; use numaflow::source::{Message, Offset, SourceReadRequest}; use numaflow::{sink, source, sourcetransform}; use tokio::sync::mpsc::Sender; use tokio_util::sync::CancellationToken; + use crate::error::Result; + use crate::forwarder::ForwarderBuilder; + use crate::sink::{SinkClient, SinkConfig}; + use crate::source::{SourceClient, SourceConfig}; + use crate::transformer::{TransformerClient, TransformerConfig}; + struct SimpleSource { yet_to_be_acked: std::sync::RwLock>, } @@ -768,13 +874,13 @@ mod tests { let forwarder_handle = tokio::spawn(async move { forwarder.start().await?; - Ok(()) + Result::<()>::Ok(()) }); // Set a timeout for the forwarder let timeout_duration = tokio::time::Duration::from_secs(1); + // The future should not complete as we should be retrying let result = tokio::time::timeout(timeout_duration, forwarder_handle).await; - let result: Result<()> = result.expect("forwarder_handle timed out").unwrap(); assert!(result.is_err()); // stop the servers diff --git a/rust/monovertex/src/metrics.rs b/rust/monovertex/src/metrics.rs index dc5dfd6dc9..f6f5519765 100644 --- a/rust/monovertex/src/metrics.rs +++ b/rust/monovertex/src/metrics.rs @@ -44,8 +44,12 @@ const READ_TOTAL: &str = "monovtx_read"; const READ_BYTES_TOTAL: &str = "monovtx_read_bytes"; const ACK_TOTAL: &str = "monovtx_ack"; const SINK_WRITE_TOTAL: &str = "monovtx_sink_write"; +const DROPPED_TOTAL: &str = "monovtx_dropped"; +const FALLBACK_SINK_WRITE_TOTAL: &str = "monovtx_fallback_sink_write"; + // pending as gauge const SOURCE_PENDING: &str = "monovtx_pending"; + // processing times as timers const E2E_TIME: &str = "monovtx_processing_time"; const READ_TIME: &str = "monovtx_read_time"; @@ -100,8 +104,12 @@ pub struct MonoVtxMetrics { pub read_bytes_total: Family, Counter>, pub ack_total: Family, Counter>, pub sink_write_total: Family, Counter>, + pub dropped_total: Family, Counter>, + pub fbsink_write_total: Family, Counter>, + // gauge pub source_pending: Family, Gauge>, + // timers pub e2e_time: Family, Histogram>, pub read_time: Family, Histogram>, @@ -118,6 +126,8 @@ impl MonoVtxMetrics { read_bytes_total: Family::, Counter>::default(), ack_total: Family::, Counter>::default(), sink_write_total: Family::, Counter>::default(), + dropped_total: Family::, Counter>::default(), + fbsink_write_total: Family::, Counter>::default(), // gauge source_pending: Family::, Gauge>::default(), // timers @@ -160,6 +170,19 @@ impl MonoVtxMetrics { "A Counter to keep track of the total number of bytes read from the source", metrics.read_bytes_total.clone(), ); + + registry.register( + DROPPED_TOTAL, + "A Counter to keep track of the total number of messages dropped by the monovtx", + metrics.dropped_total.clone(), + ); + + registry.register( + FALLBACK_SINK_WRITE_TOTAL, + "A Counter to keep track of the total number of messages written to the fallback sink", + metrics.fbsink_write_total.clone(), + ); + // gauges registry.register( SOURCE_PENDING, @@ -192,7 +215,6 @@ impl MonoVtxMetrics { "A Histogram to keep track of the total time taken to Write to the Sink, in microseconds", metrics.sink_time.clone(), ); - metrics } } diff --git a/rust/numaflow-models/src/models/backoff.rs b/rust/numaflow-models/src/models/backoff.rs new file mode 100644 index 0000000000..7d2baddcd7 --- /dev/null +++ b/rust/numaflow-models/src/models/backoff.rs @@ -0,0 +1,38 @@ +/* +Copyright 2022 The Numaproj Authors. + +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. +*/ + +// Code generated by Openapi Generator. DO NOT EDIT. + +/// Backoff : Backoff defines parameters used to systematically configure the retry strategy. + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Backoff { + #[serde(rename = "interval", skip_serializing_if = "Option::is_none")] + pub interval: Option, + /// Steps defines the number of times to try writing to a sink including retries + #[serde(rename = "steps", skip_serializing_if = "Option::is_none")] + pub steps: Option, +} + +impl Backoff { + /// Backoff defines parameters used to systematically configure the retry strategy. + pub fn new() -> Backoff { + Backoff { + interval: None, + steps: None, + } + } +} diff --git a/rust/numaflow-models/src/models/mod.rs b/rust/numaflow-models/src/models/mod.rs index 648964f907..bbb11ca261 100644 --- a/rust/numaflow-models/src/models/mod.rs +++ b/rust/numaflow-models/src/models/mod.rs @@ -6,6 +6,8 @@ pub mod abstract_vertex; pub use self::abstract_vertex::AbstractVertex; pub mod authorization; pub use self::authorization::Authorization; +pub mod backoff; +pub use self::backoff::Backoff; pub mod basic_auth; pub use self::basic_auth::BasicAuth; pub mod blackhole; @@ -124,6 +126,8 @@ pub mod redis_config; pub use self::redis_config::RedisConfig; pub mod redis_settings; pub use self::redis_settings::RedisSettings; +pub mod retry_strategy; +pub use self::retry_strategy::RetryStrategy; pub mod sasl; pub use self::sasl::Sasl; pub mod sasl_plain; diff --git a/rust/numaflow-models/src/models/retry_strategy.rs b/rust/numaflow-models/src/models/retry_strategy.rs new file mode 100644 index 0000000000..0b1a52a654 --- /dev/null +++ b/rust/numaflow-models/src/models/retry_strategy.rs @@ -0,0 +1,38 @@ +/* +Copyright 2022 The Numaproj Authors. + +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. +*/ + +// Code generated by Openapi Generator. DO NOT EDIT. + +/// RetryStrategy : RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. It includes a BackOff strategy to manage the timing of retries and defines the action to take upon failure. + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct RetryStrategy { + #[serde(rename = "backoff", skip_serializing_if = "Option::is_none")] + pub backoff: Option>, + /// OnFailure specifies the action to take when a retry fails. The default action is to retry. + #[serde(rename = "onFailure", skip_serializing_if = "Option::is_none")] + pub on_failure: Option, +} + +impl RetryStrategy { + /// RetryStrategy struct encapsulates the settings for retrying operations in the event of failures. It includes a BackOff strategy to manage the timing of retries and defines the action to take upon failure. + pub fn new() -> RetryStrategy { + RetryStrategy { + backoff: None, + on_failure: None, + } + } +} diff --git a/rust/numaflow-models/src/models/sink.rs b/rust/numaflow-models/src/models/sink.rs index aa3402f42e..91f18340eb 100644 --- a/rust/numaflow-models/src/models/sink.rs +++ b/rust/numaflow-models/src/models/sink.rs @@ -26,6 +26,8 @@ pub struct Sink { pub kafka: Option>, #[serde(rename = "log", skip_serializing_if = "Option::is_none")] pub log: Option>, + #[serde(rename = "retryStrategy", skip_serializing_if = "Option::is_none")] + pub retry_strategy: Option>, #[serde(rename = "udsink", skip_serializing_if = "Option::is_none")] pub udsink: Option>, } @@ -37,6 +39,7 @@ impl Sink { fallback: None, kafka: None, log: None, + retry_strategy: None, udsink: None, } }