Skip to content

Commit

Permalink
added balance client and invalidated balance for legacy re claiming (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
maikelmclauflin authored and evq committed Dec 3, 2019
1 parent 877449c commit a6bd304
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 21 deletions.
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ services:
- KAFKA_SSL_KEY_PASSWORD=confluent
- KAFKA_REQUIRED_ACKS=1
- "LEDGER_SERVER=https://ledger-staging.mercury.basicattentiontoken.org"
- "BALANCE_SERVER=https://balance-staging.mercury.basicattentiontoken.org"
- TOKEN_LIST
- UPHOLD_ACCESS_TOKEN
volumes:
Expand Down
7 changes: 7 additions & 0 deletions promotion/claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,13 @@ func (service *Service) ClaimPromotionForWallet(
return nil, err
}

if claim.LegacyClaimed {
err = service.balanceClient.InvalidateBalance(ctx, walletID)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
}
}

go func() {
_, err := service.RunNextClaimJob(ctx)
if err != nil {
Expand Down
64 changes: 43 additions & 21 deletions promotion/controllers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/brave-intl/bat-go/utils/altcurrency"
"github.com/brave-intl/bat-go/utils/cbr"
mockcb "github.com/brave-intl/bat-go/utils/cbr/mock"
mockbalance "github.com/brave-intl/bat-go/utils/clients/balance/mock"
"github.com/brave-intl/bat-go/utils/httpsignature"
mockledger "github.com/brave-intl/bat-go/utils/ledger/mock"
mockreputation "github.com/brave-intl/bat-go/utils/reputation/mock"
Expand Down Expand Up @@ -787,43 +788,49 @@ func (suite *ControllersTestSuite) TestClaimCompatability() {
suite.Require().NoError(err, "could not connect to db")
mockReputation := mockreputation.NewMockClient(mockCtrl)
mockCB := mockcb.NewMockClient(mockCtrl)
mockBalance := mockbalance.NewMockClient(mockCtrl)

service := &Service{
datastore: pg,
reputationClient: mockReputation,
cbClient: mockCB,
balanceClient: mockBalance,
}

scenarios := []struct {
Legacy bool
Redeemed bool
ChecksReputation bool
WillSign bool
Type string
Legacy bool
Redeemed bool
ChecksReputation bool
InvalidatesBalance bool
Type string
}{
{
Legacy: false,
Redeemed: false,
ChecksReputation: true,
Type: "ugp",
Legacy: false,
Redeemed: false,
ChecksReputation: true,
InvalidatesBalance: false,
Type: "ugp",
},
{
Legacy: false,
Redeemed: true,
ChecksReputation: false,
Type: "ugp",
Legacy: false,
Redeemed: true,
ChecksReputation: false,
InvalidatesBalance: false,
Type: "ugp",
},
{
Legacy: true,
Redeemed: false,
ChecksReputation: false,
Type: "ugp",
Legacy: true,
Redeemed: false,
ChecksReputation: false,
InvalidatesBalance: true,
Type: "ugp",
},
{
Legacy: true,
Redeemed: true,
ChecksReputation: false,
Type: "ugp",
Legacy: true,
Redeemed: true,
ChecksReputation: false,
InvalidatesBalance: false,
Type: "ugp",
},
}
for _, test := range scenarios {
Expand Down Expand Up @@ -883,6 +890,13 @@ func (suite *ControllersTestSuite) TestClaimCompatability() {
true,
nil,
)
} else {
mockBalance.EXPECT().
InvalidateBalance(
gomock.Any(),
gomock.Eq(walletID),
).
Return(nil)
}
_ = suite.ClaimGrant(service, *w, privKey, promotion, blindedCreds)
}
Expand All @@ -899,6 +913,14 @@ func (suite *ControllersTestSuite) TestClaimCompatability() {
nil,
)
}
if test.InvalidatesBalance {
mockBalance.EXPECT().
InvalidateBalance(
gomock.Any(),
gomock.Eq(walletID),
).
Return(nil)
}

// if NOT redeemed, the mockCB's SignCredentials will be used up here
_ = suite.ClaimGrant(service, *w, privKey, promotion, blindedCreds)
Expand Down
8 changes: 8 additions & 0 deletions promotion/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/brave-intl/bat-go/utils/cbr"
"github.com/brave-intl/bat-go/utils/clients/balance"
"github.com/brave-intl/bat-go/utils/ledger"
"github.com/brave-intl/bat-go/utils/reputation"
"github.com/linkedin/goavro"
Expand All @@ -28,6 +29,7 @@ type Service struct {
cbClient cbr.Client
ledgerClient ledger.Client
reputationClient reputation.Client
balanceClient balance.Client
codecs map[string]*goavro.Codec
kafkaWriter *kafka.Writer
kafkaDialer *kafka.Dialer
Expand Down Expand Up @@ -168,12 +170,18 @@ func InitService(datastore Datastore, roDatastore ReadOnlyDatastore) (*Service,
return nil, err
}

balanceClient, err := balance.New()
if err != nil {
return nil, err
}

service := &Service{
datastore: datastore,
roDatastore: roDatastore,
cbClient: cbClient,
ledgerClient: ledgerClient,
reputationClient: reputationClient,
balanceClient: balanceClient,
}
err = service.InitKafka()
if err != nil {
Expand Down
126 changes: 126 additions & 0 deletions utils/clients/balance/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package balance

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/http/httputil"
"net/url"
"os"
"time"

"github.com/brave-intl/bat-go/utils/closers"
"github.com/rs/zerolog/log"
uuid "github.com/satori/go.uuid"
)

// Client abstracts over the underlying client
type Client interface {
InvalidateBalance(ctx context.Context, id uuid.UUID) error
}

// HTTPClient wraps http.Client for interacting with the ledger server
type HTTPClient struct {
BaseURL *url.URL
AuthToken string

client *http.Client
}

// New returns a new HTTPClient, retrieving the base URL from the environment
func New() (*HTTPClient, error) {
serverURL := os.Getenv("BALANCE_SERVER")

if len(serverURL) == 0 {
return nil, errors.New("BALANCE_SERVER was empty")
}

baseURL, err := url.Parse(serverURL)

if err != nil {
return nil, err
}

return &HTTPClient{
BaseURL: baseURL,
AuthToken: os.Getenv("BALANCE_TOKEN"),
client: &http.Client{
Timeout: time.Second * 10,
},
}, nil
}

func (c *HTTPClient) newRequest(ctx context.Context, method, path string, body interface{}) (*http.Request, error) {
url := c.BaseURL.ResolveReference(&url.URL{Path: path})

var buf io.ReadWriter
if body != nil {
buf = new(bytes.Buffer)
err := json.NewEncoder(buf).Encode(body)
if err != nil {
return nil, err
}
}

req, err := http.NewRequest(method, url.String(), buf)
if err != nil {
return nil, err
}
req.Header.Set("accept", "application/json")

if body != nil {
req.Header.Add("content-type", "application/json")
}

logger := log.Ctx(ctx)

dump, err := httputil.DumpRequestOut(req, true)
if err != nil {
panic(err)
}

logger.Debug().Str("type", "http.Request").Msg(string(dump))

req.Header.Set("authorization", "Bearer "+c.AuthToken)

return req, err
}

func (c *HTTPClient) do(req *http.Request, v interface{}) (*http.Response, error) {
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer closers.Panic(resp.Body)

if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
if v != nil {
err = json.NewDecoder(resp.Body).Decode(v)
if err != nil {
return resp, err
}
}
return resp, nil
}
return resp, fmt.Errorf("Request error: %d", resp.StatusCode)
}

// InvalidateBalance invalidates the cached value on balance
func (c *HTTPClient) InvalidateBalance(ctx context.Context, id uuid.UUID) error {
req, err := c.newRequest(ctx, "DELETE", "v2/wallet/"+id.String()+"/balance", nil)
if err != nil {
return err
}

_, err = c.do(req, nil)

if err != nil {
return err
}

return nil
}
49 changes: 49 additions & 0 deletions utils/clients/balance/mock/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a6bd304

Please sign in to comment.