Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

instancestorage: read instances in a transaction #95800

Merged
merged 1 commit into from
Jan 27, 2023

Conversation

healthy-pod
Copy link
Contributor

This code change adds (instancestorage.Reader).GetAllInstancesUsingTxn to read all instances using the given *kv.Txn.

Release note: None
Epic: CRDB-18735

@cockroach-teamcity
Copy link
Member

This change is Reviewable

func (r *Reader) getAllUniqueLiveInstances(
ctx context.Context, rows []instancerow,
) ([]instancerow, error) {
instancesSet := make(map[base.SQLInstanceID]struct{}, len(rows))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is needed. See the logic below after the sort.

Comment on lines 202 to 214
instances, err := reader.GetAllInstances(ctx)
if err != nil {
return err
}
sortInstances(instances)
return testOutputFn(instanceIDs, rpcAddresses, sqlAddresses, sessionIDs, localities, instances)
if err := testOutputFn(instanceIDs, rpcAddresses, sqlAddresses, sessionIDs, localities, instances); err != nil {
return err
}
instancesUsingTxn, err := getInstancesUsingTxnWrapper()
if err != nil {
return err
}
return testOutputFn(instanceIDs, rpcAddresses, sqlAddresses, sessionIDs, localities, instancesUsingTxn)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about a helper to remove some of this boilerplate and to make the test easier to read?
Firstly, let's make a structure to pass to testOutputFn, let's call it expectations. Then, let's make a helper

type expectations struct { /* ... */ }
testOutputFn := func(exp expectations, actualInstances []sqlinstance.InstanceInfo) { /* ... */ }

expectationsFromOffset := func(offset int) expectations {
    return expectations{
     instanceIDs: instanceIDs[offset:],
     rpcAddresses: rpcAddresses[offset:],
     sqlAddresses: sqlAddresses[offset:],
     sessionIDs: sessionIDs[offset:],
     localities: localities[offset:]
    }
}
// ...
verifyInstancesWithGetter := func(t *testing.T, name string, exp expectations, getInstances func()([]sqlinstance.InstanceInfo, error)) (retErr error) {
    defer func() { errors.Wrap(retErr, name) }
    instances, err := getInstances()
    if err != nil {
        return err
    }
    sortInstances(instances)
    return testOutputFn(exp, instances)
}
verifyInstances := func(t *testing.T, exp expectations) {
    if err := verifyInstancesWithGetter(t, "reader", offset, func() ([]sqlinstance.InstanceInfo, error) {
    		return reader.GetAllInstances(ctx)
    }); err != nil {
        return err
    }
    return verifyInstancesWithGetter(t, "txn", offset, func() ([]sqlinstance.InstanceInfo, error) {
    		return getInstancesUsingTxn(t)
    })
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@@ -175,6 +175,15 @@ func TestReader(t *testing.T) {
}
return nil
}
getInstancesUsingTxnWrapper := func() ([]sqlinstance.InstanceInfo, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you should take t as a parameter to deal with future refactorings and subtests. Also, I don't think the Wrapper suffix adds value; just call it getInstancedUsingTxn

@@ -175,6 +175,15 @@ func TestReader(t *testing.T) {
}
return nil
}
getInstancesUsingTxnWrapper := func() ([]sqlinstance.InstanceInfo, error) {
txn := s.DB().NewTxn(ctx, "testing GetAllInstancesUsingTxn")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NewTxn is low-level and generally to be avoided. Instead you ought to use s.DB().Txn

if err != nil {
return nil, err
}
sortInstances(instancesUsingTxn)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leave this for later. It'll make the next helper simpler.

@healthy-pod healthy-pod force-pushed the transactional-instances-read branch 2 times, most recently from 068e40e to 694d363 Compare January 26, 2023 20:14
@healthy-pod healthy-pod requested a review from ajwerner January 26, 2023 20:16
@healthy-pod
Copy link
Contributor Author

Ready for a second pass

@healthy-pod healthy-pod force-pushed the transactional-instances-read branch from 694d363 to 07111ed Compare January 26, 2023 20:46
Copy link
Contributor

@ajwerner ajwerner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the comments are all nits

Comment on lines 149 to 160
instances := make([]sqlinstance.InstanceInfo, 0, len(rows))
for _, row := range filteredRows {
instanceInfo := sqlinstance.InstanceInfo{
InstanceID: row.instanceID,
InstanceRPCAddr: row.rpcAddr,
InstanceSQLAddr: row.sqlAddr,
SessionID: row.sessionID,
Locality: row.locality,
}
instances = append(instances, instanceInfo)
}
return instances, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extract a helper to convert the []instancerow into []sqlinstance.InstanceInfo. I'd probably also extract a constructor for a single InstanceInfo from a row like makeInstanceInfo(row instancerow) sqlinstance.InstanceInfo so that is' like:

func makeInstanceInfos(rows []instancerow) []sqlinstance.InstanceInfo {
    ret := make([]sqlinstance.InstanceInfo, len(rows))
    for i := range rows {
        ret[i] = makeInstanceInfo(rows[i])
    }
    return ret
}

@@ -225,8 +264,9 @@ func (r *Reader) GetAllInstances(
return sqlInstances, nil
}

func (r *Reader) getAllLiveInstances(ctx context.Context) ([]instancerow, error) {
rows := r.getAllInstanceRows()
func (r *Reader) getAllUniqueLiveInstances(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uber-nit: I think I'd take this off of the *Reader and make it a free standing function which takes a sqlliveness.Reader. I'd probably call it selectDistinctLiveRows(context.Context, sqlliveness.Reader, []instanceRow) ([]instancerow, error)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note also that the function will modify the slice in place.

// GetAllInstancesUsingTxn reads all instances using the given transaction and returns
// live instances only.
func (r *Reader) GetAllInstancesUsingTxn(
ctx context.Context, tenantCodec keys.SQLCodec, tableID catid.DescID, txn *kv.Txn,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: everywhere else we just call this codec

}
sortInstances(instances)
return testOutputFn(
return verifyInstances(t, expectations{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect the linter to want field names, generally our style is to write them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we lint against that although it'd be nice. I didn't add them initially because I assumed the types would be enough.

@healthy-pod healthy-pod force-pushed the transactional-instances-read branch from 07111ed to df9ff31 Compare January 26, 2023 23:32
@healthy-pod
Copy link
Contributor Author

TFTR!

This code change adds `(instancestorage.Reader).GetAllInstancesUsingTxn`
to read all instances using the given `*kv.Txn`.

Release note: None
Epic: CRDB-18735
@healthy-pod healthy-pod force-pushed the transactional-instances-read branch from df9ff31 to b88b17c Compare January 27, 2023 01:38
@healthy-pod
Copy link
Contributor Author

bors r=ajwerner

@craig
Copy link
Contributor

craig bot commented Jan 27, 2023

Build succeeded:

@craig craig bot merged commit efb4481 into cockroachdb:master Jan 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants