Skip to content

Commit

Permalink
Initial correctifier code.
Browse files Browse the repository at this point in the history
  • Loading branch information
schmidtw committed Mar 12, 2024
1 parent ac04be7 commit cf93c70
Show file tree
Hide file tree
Showing 4 changed files with 320 additions and 0 deletions.
51 changes: 51 additions & 0 deletions wrpcorrectify/correctify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: 2022 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package wrpcorrectify

import (
"context"

"github.com/xmidt-org/wrp-go/v3"
)

// Correctifier applies a series of normalizing options to a WRP message.
type Correctifier struct {
opts []Option
}

// Option is a functional option for normalizing a WRP message.
type Option interface {
// Correctify applies the option to the given message.
Correctify(context.Context, *wrp.Message) error
}

// OptionFunc is an adapter to allow the use of ordinary functions as
// normalizing options.
type OptionFunc func(context.Context, *wrp.Message) error

var _ Option = OptionFunc(nil)

func (f OptionFunc) Correctify(ctx context.Context, m *wrp.Message) error {
return f(ctx, m)

Check warning on line 30 in wrpcorrectify/correctify.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/correctify.go#L29-L30

Added lines #L29 - L30 were not covered by tests
}

// New creates a new Normalizer with the given options.
func New(opts ...Option) *Correctifier {
return &Correctifier{
opts: opts,
}

Check warning on line 37 in wrpcorrectify/correctify.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/correctify.go#L34-L37

Added lines #L34 - L37 were not covered by tests
}

// Correctify applies the normalizing options to the message or returns an error
// if any of the options fail.
func (n *Correctifier) Correctify(ctx context.Context, m *wrp.Message) error {
for _, opt := range n.opts {
if opt != nil {
if err := opt.Correctify(ctx, m); err != nil {
return err
}

Check warning on line 47 in wrpcorrectify/correctify.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/correctify.go#L42-L47

Added lines #L42 - L47 were not covered by tests
}
}
return nil

Check warning on line 50 in wrpcorrectify/correctify.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/correctify.go#L50

Added line #L50 was not covered by tests
}
10 changes: 10 additions & 0 deletions wrpcorrectify/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-FileCopyrightText: 2022 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package wrpcorrectify

import "errors"

var (
ErrorInvalidMessageType = errors.New("invalid message type")
)
56 changes: 56 additions & 0 deletions wrpcorrectify/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: 2022 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package wrpcorrectify

import (
"context"

"github.com/prometheus/client_golang/prometheus"
"github.com/xmidt-org/touchstone"
"github.com/xmidt-org/wrp-go/v3"
)

// CounterMetric provides a counter metric that can be used to track the number
// of times a specific error occurs.
type CounterMetric struct {
Factory *touchstone.Factory
Name string
Help string
Labels []string
}

type metricPairs string

var mPairs = metricPairs("pairs")

// Option takes an Option and returns a new Option that increments the counter
// metric if the original Option returns an error.
func (cm CounterMetric) Option(opt Option) Option {
metric, err := cm.Factory.NewCounterVec(
prometheus.CounterOpts{
Name: cm.Name,
Help: cm.Help,
},
cm.Labels...,
)

if err != nil {
return ErrorOption(err)
}

Check warning on line 40 in wrpcorrectify/metrics.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/metrics.go#L29-L40

Added lines #L29 - L40 were not covered by tests

return OptionFunc(func(ctx context.Context, m *wrp.Message) error {
err := opt.Correctify(ctx, m)
if err != nil {
pairs := ctx.Value(mPairs).(prometheus.Labels)
metric.With(pairs).Add(1.0)
}
return err

Check warning on line 48 in wrpcorrectify/metrics.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/metrics.go#L42-L48

Added lines #L42 - L48 were not covered by tests
})
}

// WithMetricLabels returns a new context with the Prometheus labels added so
// that the labels can be used to increment the counter metric.
func WithMetricLabels(ctx context.Context, l prometheus.Labels) context.Context {
return context.WithValue(ctx, mPairs, l)

Check warning on line 55 in wrpcorrectify/metrics.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/metrics.go#L54-L55

Added lines #L54 - L55 were not covered by tests
}
203 changes: 203 additions & 0 deletions wrpcorrectify/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
// SPDX-FileCopyrightText: 2022 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package wrpcorrectify

import (
"context"
"strconv"
"time"

"github.com/google/uuid"
"github.com/xmidt-org/wrp-go/v3"
)

// ErrorOption returns an option that always returns the given error.
func ErrorOption(err error) Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
return err
})

Check warning on line 19 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L16-L19

Added lines #L16 - L19 were not covered by tests
}

// Options returns a new option that applies all of the given options in order.
func Options(opts ...Option) Option {
return OptionFunc(func(ctx context.Context, m *wrp.Message) error {
for _, opt := range opts {
if opt != nil {
if err := opt.Correctify(ctx, m); err != nil {
return err
}

Check warning on line 29 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L23-L29

Added lines #L23 - L29 were not covered by tests
}
}
return nil

Check warning on line 32 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L32

Added line #L32 was not covered by tests
})
}

// ReplaceAnySelfLocator replaces any `self:` based locator with the scheme and
// authority of the given locator. If the given locator is not valid, the
// option returns an error.
func ReplaceAnySelfLocator(me string) Option {
return Options(
ReplaceSourceSelfLocator(me),
ReplaceDestinationSelfLocator(me),
)

Check warning on line 43 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L39-L43

Added lines #L39 - L43 were not covered by tests
}

// ReplaceSourceSelfLocator replaces a `self:` based source locator with the
// scheme and authority of the given locator. If the given locator is not valid,
// the option returns an error.
func ReplaceSourceSelfLocator(me string) Option {
full, err := wrp.ParseLocator(me)
if err != nil {
return ErrorOption(err)
}

Check warning on line 53 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L49-L53

Added lines #L49 - L53 were not covered by tests

return OptionFunc(func(_ context.Context, m *wrp.Message) error {
src, err := wrp.ParseLocator(m.Source)
if err != nil {
return err
}

Check warning on line 59 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L55-L59

Added lines #L55 - L59 were not covered by tests

if src.Scheme == "self" {
src.Scheme = full.Scheme
m.Source = src.String()
}

Check warning on line 64 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L61-L64

Added lines #L61 - L64 were not covered by tests

return nil

Check warning on line 66 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L66

Added line #L66 was not covered by tests
})
}

// ReplaceDestinationSelfLocator replaces the destination of the message with the
// given locator if the destination is a `self:` based locator. If the given
// locator is not valid, the option returns an error.
func ReplaceDestinationSelfLocator(me string) Option {
full, err := wrp.ParseLocator(me)
if err != nil {
return ErrorOption(err)
}

Check warning on line 77 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L73-L77

Added lines #L73 - L77 were not covered by tests

return OptionFunc(func(_ context.Context, m *wrp.Message) error {
dst, err := wrp.ParseLocator(m.Destination)
if err != nil {
return err
}

Check warning on line 83 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L79-L83

Added lines #L79 - L83 were not covered by tests

if dst.Scheme == "self" {
dst.Scheme = full.Scheme
m.Destination = dst.String()
}

Check warning on line 88 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L85-L88

Added lines #L85 - L88 were not covered by tests

return nil

Check warning on line 90 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L90

Added line #L90 was not covered by tests
})
}

// EnsureTransactionUUID ensures that the message has a transaction UUID. If
// the message does not have a transaction UUID, a new one is generated.
func EnsureTransactionUUID() Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
if m.TransactionUUID == "" {
id, err := uuid.NewRandom()
if err != nil {
return err
}

Check warning on line 102 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L96-L102

Added lines #L96 - L102 were not covered by tests

m.TransactionUUID = id.String()

Check warning on line 104 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L104

Added line #L104 was not covered by tests
}
return nil

Check warning on line 106 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L106

Added line #L106 was not covered by tests
})
}

// EnsurePartnerID ensures that the message has the given partner ID in
// the list.
func EnsurePartnerID(partnerID string) Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
if m.PartnerIDs == nil {
m.PartnerIDs = make([]string, 0, 1)
}
for _, id := range m.PartnerIDs {
if id == partnerID {
return nil
}

Check warning on line 120 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L112-L120

Added lines #L112 - L120 were not covered by tests
}
m.PartnerIDs = append(m.PartnerIDs, partnerID)
return nil

Check warning on line 123 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L122-L123

Added lines #L122 - L123 were not covered by tests
})
}

// SetPartnerID ensures that the message has only the given partner ID.
func SetPartnerID(partnerID string) Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
if m.PartnerIDs == nil {
m.PartnerIDs = make([]string, 0, 1)
}
m.PartnerIDs = append(m.PartnerIDs, partnerID)
return nil

Check warning on line 134 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L128-L134

Added lines #L128 - L134 were not covered by tests
})
}

// SetSessionID ensures that the message has the given session ID.
func SetSessionID(sessionID string) Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
m.SessionID = sessionID
return nil
})

Check warning on line 143 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L139-L143

Added lines #L139 - L143 were not covered by tests
}

// EnsureMetadataString ensures that the message has the given string metadata.
func EnsureMetadataString(key, value string) Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
if m.Metadata == nil {
m.Metadata = make(map[string]string)
}
m.Metadata[key] = value
return nil

Check warning on line 153 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L147-L153

Added lines #L147 - L153 were not covered by tests
})
}

// EnsureMetadataTime ensures that the message has the given time metadata.
func EnsureMetadataTime(key string, t time.Time) Option {
return EnsureMetadataString(key, t.Format(time.RFC3339))

Check warning on line 159 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L158-L159

Added lines #L158 - L159 were not covered by tests
}

// EnsureMetadataInt ensures that the message has the given integer metadata.
func EnsureMetadataInt(key string, i int64) Option {
return EnsureMetadataString(key, strconv.FormatInt(i, 10))

Check warning on line 164 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L163-L164

Added lines #L163 - L164 were not covered by tests
}

// ValidateSource ensures that the source locator is valid.
func ValidateSource() Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
if _, err := wrp.ParseLocator(m.Source); err != nil {
return err
}
return nil

Check warning on line 173 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L168-L173

Added lines #L168 - L173 were not covered by tests
})
}

// ValidateDestination ensures that the destination locator is valid.
func ValidateDestination() Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
if _, err := wrp.ParseLocator(m.Destination); err != nil {
return err
}
return nil

Check warning on line 183 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L178-L183

Added lines #L178 - L183 were not covered by tests
})
}

func ValidateMessageType() Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
if m.Type <= wrp.Invalid1MessageType || m.Type >= wrp.LastMessageType {
return ErrorInvalidMessageType
}
return nil

Check warning on line 192 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L187-L192

Added lines #L187 - L192 were not covered by tests
})
}

func ValidateOnlyUTF8Strings() Option {
return OptionFunc(func(_ context.Context, m *wrp.Message) error {
if err := wrp.UTF8(m); err != nil {
return err
}
return nil

Check warning on line 201 in wrpcorrectify/options.go

View check run for this annotation

Codecov / codecov/patch

wrpcorrectify/options.go#L196-L201

Added lines #L196 - L201 were not covered by tests
})
}

0 comments on commit cf93c70

Please sign in to comment.