Repository: etcd-io/etcd
File: tests/robustness/traffic/etcd.go (Go)

Code before:
	leaseStorage identity.LeaseIDStorage
}

func (c etcdTrafficClient) Request(ctx context.Context, request etcdRequestType, lastRev int64) (rev int64, err error) {
	opCtx, cancel := context.WithTimeout(ctx, RequestTimeout)
	defer cancel()

	var limit int64
	switch request {
	case StaleGet:
		var resp *clientv3.GetResponse
		resp, err = c.client.Get(opCtx, c.keyStore.GetKey(), clientv3.WithRev(lastRev))
		if err == nil {
			rev = resp.Header.Revision
		}
	case Get:
		var resp *clientv3.GetResponse
		resp, err = c.client.Get(opCtx, c.keyStore.GetKey(), clientv3.WithRev(0))
		if err == nil {
			rev = resp.Header.Revision
		}
	case List:
		var resp *clientv3.GetResponse
		resp, err = c.client.Range(ctx, c.keyStore.GetPrefix(), clientv3.GetPrefixRangeEnd(c.keyStore.GetPrefix()), 0, limit)
		if resp != nil {
			if resp.Header.GetRevision() > c.keyStore.GetLatestRevision() {
				// sync keys to prevent key leaks
				c.keyStore.SyncKeys(resp)
			}
			rev = resp.Header.Revision
		}
	case StaleList:
		var resp *clientv3.GetResponse
		resp, err = c.client.Range(ctx, c.keyStore.GetPrefix(), clientv3.GetPrefixRangeEnd(c.keyStore.GetPrefix()), lastRev, limit)
		if resp != nil {
			rev = resp.Header.Revision
		}
	case Put:
		var resp *clientv3.PutResponse
		resp, err = c.client.Put(opCtx, c.keyStore.GetKey(), fmt.Sprintf("%d", c.idProvider.NewRequestID()))
		if resp != nil {
			rev = resp.Header.Revision
		}
	case LargePut:
		var resp *clientv3.PutResponse
		resp, err = c.client.Put(opCtx, c.keyStore.GetKey(), random.RandString(c.largePutSize))
		if resp != nil {
			rev = resp.Header.Revision
		}
	case Delete:
		var resp *clientv3.DeleteResponse

Review comment (suggestion):
This check should be under lock. Please just move it under `SyncKeys`.

Code after:
	leaseStorage identity.LeaseIDStorage
}

func (c etcdTrafficClient) Request(ctx context.Context, request etcdRequestType, lastRev int64) (rev int64, err error) {
	opCtx, cancel := context.WithTimeout(ctx, RequestTimeout)
	defer cancel()

	var limit int64
	switch request {
	case StaleGet:
		var resp *clientv3.GetResponse
		resp, err = c.client.Get(opCtx, c.keyStore.GetKey(), clientv3.WithRev(lastRev))
		if err == nil {
			rev = resp.Header.Revision
		}
	case Get:
		var resp *clientv3.GetResponse
		resp, err = c.client.Get(opCtx, c.keyStore.GetKey(), clientv3.WithRev(0))
		if err == nil {
			rev = resp.Header.Revision
		}
	case List:
		var resp *clientv3.GetResponse
		resp, err = c.client.Range(ctx, c.keyStore.GetPrefix(), clientv3.GetPrefixRangeEnd(c.keyStore.GetPrefix()), 0, limit)
		if resp != nil {
			c.keyStore.SyncKeys(resp)
			rev = resp.Header.Revision
		}
	case StaleList:
		var resp *clientv3.GetResponse
		resp, err = c.client.Range(ctx, c.keyStore.GetPrefix(), clientv3.GetPrefixRangeEnd(c.keyStore.GetPrefix()), lastRev, limit)
		if resp != nil {
			rev = resp.Header.Revision
		}
	case Put:
		var resp *clientv3.PutResponse
		resp, err = c.client.Put(opCtx, c.keyStore.GetKey(), fmt.Sprintf("%d", c.idProvider.NewRequestID()))
		if resp != nil {
			rev = resp.Header.Revision
		}
	case LargePut:
		var resp *clientv3.PutResponse
		resp, err = c.client.Put(opCtx, c.keyStore.GetKey(), random.RandString(c.largePutSize))
		if resp != nil {
			rev = resp.Header.Revision
		}
	case Delete:
		var resp *clientv3.DeleteResponse
		resp, err = c.client.Delete(opCtx, c.keyStore.GetKeyForDelete())
		if resp != nil {
			rev = resp.Header.Revision