github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/nonce_sql.go (about) 1 // Copyright © 2021 Kaleido, Inc. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package sqlcommon 18 19 import ( 20 "context" 21 "database/sql" 22 23 sq "github.com/Masterminds/squirrel" 24 "github.com/kaleido-io/firefly/internal/i18n" 25 "github.com/kaleido-io/firefly/internal/log" 26 "github.com/kaleido-io/firefly/pkg/database" 27 "github.com/kaleido-io/firefly/pkg/fftypes" 28 ) 29 30 var ( 31 nonceColumns = []string{ 32 "context", 33 "nonce", 34 "group_hash", 35 "topic", 36 } 37 nonceFilterTypeMap = map[string]string{ 38 "group": "group_hash", 39 } 40 ) 41 42 func (s *SQLCommon) UpsertNonceNext(ctx context.Context, nonce *fftypes.Nonce) (err error) { 43 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 44 if err != nil { 45 return err 46 } 47 defer s.rollbackTx(ctx, tx, autoCommit) 48 49 existing := false 50 // Do a select within the transaction to detemine if the UUID already exists 51 nonceRows, err := s.queryTx(ctx, tx, 52 sq.Select("nonce", s.provider.SequenceField("")). 53 From("nonces"). 54 Where( 55 sq.Eq{"context": nonce.Context}), 56 ) 57 if err != nil { 58 return err 59 } 60 existing = nonceRows.Next() 61 62 if existing { 63 var existingNonce, sequence int64 64 err := nonceRows.Scan(&existingNonce, &sequence) 65 if err != nil { 66 nonceRows.Close() 67 return i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "nonces") 68 } 69 nonce.Nonce = existingNonce + 1 70 nonceRows.Close() 71 72 // Update the nonce 73 if err = s.updateTx(ctx, tx, 74 sq.Update("nonces"). 75 Set("nonce", nonce.Nonce). 76 Where(sq.Eq{s.provider.SequenceField(""): sequence}), 77 ); err != nil { 78 return err 79 } 80 } else { 81 nonceRows.Close() 82 83 nonce.Nonce = 0 84 if _, err = s.insertTx(ctx, tx, 85 sq.Insert("nonces"). 86 Columns(nonceColumns...). 87 Values( 88 nonce.Context, 89 nonce.Nonce, 90 nonce.Group, 91 nonce.Topic, 92 ), 93 ); err != nil { 94 return err 95 } 96 } 97 98 return s.commitTx(ctx, tx, autoCommit) 99 } 100 101 func (s *SQLCommon) nonceResult(ctx context.Context, row *sql.Rows) (*fftypes.Nonce, error) { 102 nonce := fftypes.Nonce{} 103 err := row.Scan( 104 &nonce.Context, 105 &nonce.Nonce, 106 &nonce.Group, 107 &nonce.Topic, 108 ) 109 if err != nil { 110 return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "nonces") 111 } 112 return &nonce, nil 113 } 114 115 func (s *SQLCommon) GetNonce(ctx context.Context, context *fftypes.Bytes32) (message *fftypes.Nonce, err error) { 116 117 rows, err := s.query(ctx, 118 sq.Select(nonceColumns...). 119 From("nonces"). 120 Where(sq.Eq{"context": context}), 121 ) 122 if err != nil { 123 return nil, err 124 } 125 defer rows.Close() 126 127 if !rows.Next() { 128 log.L(ctx).Debugf("Nonce '%s' not found", context) 129 return nil, nil 130 } 131 132 nonce, err := s.nonceResult(ctx, rows) 133 if err != nil { 134 return nil, err 135 } 136 137 return nonce, nil 138 } 139 140 func (s *SQLCommon) GetNonces(ctx context.Context, filter database.Filter) (message []*fftypes.Nonce, err error) { 141 142 query, err := s.filterSelect(ctx, "", sq.Select(nonceColumns...).From("nonces"), filter, nonceFilterTypeMap) 143 if err != nil { 144 return nil, err 145 } 146 147 rows, err := s.query(ctx, query) 148 if err != nil { 149 return nil, err 150 } 151 defer rows.Close() 152 153 nonce := []*fftypes.Nonce{} 154 for rows.Next() { 155 d, err := s.nonceResult(ctx, rows) 156 if err != nil { 157 return nil, err 158 } 159 nonce = append(nonce, d) 160 } 161 162 return nonce, err 163 164 } 165 166 func (s *SQLCommon) DeleteNonce(ctx context.Context, context *fftypes.Bytes32) (err error) { 167 168 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 169 if err != nil { 170 return err 171 } 172 defer s.rollbackTx(ctx, tx, autoCommit) 173 174 err = s.deleteTx(ctx, tx, sq.Delete("nonces").Where(sq.Eq{ 175 "context": context, 176 })) 177 if err != nil { 178 return err 179 } 180 181 return s.commitTx(ctx, tx, autoCommit) 182 }