github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/closedts/minprop/doc_test.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package minprop
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"sort"
    17  	"strings"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/closedts/ctpb"
    20  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    21  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    22  )
    23  
    24  func Example() {
    25  	ctx := context.Background()
    26  
    27  	tracker := NewTracker()
    28  	const ep1 ctpb.Epoch = 1
    29  	fmt.Println("The newly initialized tracker has a zero closed timestamp:")
    30  	fmt.Println(tracker)
    31  
    32  	fmt.Println("A first command arrives on range 12 (though the range isn't known yet to the Tracker).")
    33  	ts, done1 := tracker.Track(ctx)
    34  	fmt.Println("All commands initially start out on the right. The command has its timestamp forwarded to", ts, ".")
    35  	fmt.Println(tracker)
    36  
    37  	fmt.Println("Two more commands arrive, on r1 and r12.")
    38  	_, done2 := tracker.Track(ctx)
    39  	_, done3 := tracker.Track(ctx)
    40  	fmt.Println(tracker)
    41  
    42  	fmt.Println("The command on r1 finishes evaluating at Lease Applied Index 10 and lets the Tracker know.")
    43  	done2(ctx, ep1, 1, 10)
    44  	fmt.Println(tracker)
    45  
    46  	fmt.Println("The command on r12 also finishes quickly, at LAI 77.")
    47  	done3(ctx, ep1, 12, 77)
    48  	fmt.Println(tracker)
    49  
    50  	fmt.Println("The system closes out a timestamp (registering 1000 as the next timestamp to close out).")
    51  	closed1, mlai1, _ := tracker.Close(hlc.Timestamp{WallTime: 1e9}, ep1)
    52  	fmt.Println("No problem: nothing is tracked on the left side; returns:", closed1, "and", mlaiString(mlai1))
    53  	fmt.Println("Note how the items on the right have moved to the left, as they are relevant for the")
    54  	fmt.Println("next call to Close.")
    55  	fmt.Println(tracker)
    56  
    57  	fmt.Println("Nothing happens for a while until the system tries to close out the next timestamp.")
    58  	fmt.Println("However, the very first proposal is still tracked and blocks progress.")
    59  	closed2, mlai2, _ := tracker.Close(hlc.Timestamp{WallTime: 2e9}, ep1)
    60  	fmt.Println("The call returns a no-op in the form", closed2, mlaiString(mlai2), ".")
    61  	fmt.Println(tracker)
    62  
    63  	ts4, done4 := tracker.Track(ctx)
    64  	fmt.Println("A new command gets tracked on r12 (and is forwarded to", ts4, "(if necessary).")
    65  	fmt.Println("It terminates quickly, leaving an MLAI entry of 78 behind.")
    66  	done4(ctx, ep1, 12, 78)
    67  	fmt.Println(tracker)
    68  
    69  	fmt.Println("Finally! The slow evaluation finishes and the command gets proposed at index 79.")
    70  	fmt.Println("Note that the right now tracks a smaller value of 78. Consumers have to keep the")
    71  	fmt.Println("maximum they've seen.")
    72  	done1(ctx, ep1, 12, 79)
    73  	fmt.Println(tracker)
    74  
    75  	closed3, mlai3, _ := tracker.Close(hlc.Timestamp{WallTime: 3e9}, ep1)
    76  	fmt.Println("The next call to Close() is successful and returns:", closed3, "and", mlaiString(mlai3))
    77  	fmt.Println(tracker)
    78  
    79  	// Output:
    80  	// The newly initialized tracker has a zero closed timestamp:
    81  	//
    82  	//   closed=0,0
    83  	//       |            next=0,1
    84  	//       |          left | right
    85  	//       |             0 # 0
    86  	//       |             1 e 1
    87  	//       v               v
    88  	// ---------------------------------------------------------> time
    89  	//
    90  	// A first command arrives on range 12 (though the range isn't known yet to the Tracker).
    91  	// All commands initially start out on the right. The command has its timestamp forwarded to 0,2 .
    92  	//
    93  	//   closed=0,0
    94  	//       |            next=0,1
    95  	//       |          left | right
    96  	//       |             0 # 1
    97  	//       |             1 e 1
    98  	//       v               v
    99  	// ---------------------------------------------------------> time
   100  	//
   101  	// Two more commands arrive, on r1 and r12.
   102  	//
   103  	//   closed=0,0
   104  	//       |            next=0,1
   105  	//       |          left | right
   106  	//       |             0 # 3
   107  	//       |             1 e 1
   108  	//       v               v
   109  	// ---------------------------------------------------------> time
   110  	//
   111  	// The command on r1 finishes evaluating at Lease Applied Index 10 and lets the Tracker know.
   112  	//
   113  	//   closed=0,0
   114  	//       |            next=0,1
   115  	//       |          left | right
   116  	//       |             0 # 2
   117  	//       |             1 e 1
   118  	//       |               @ 10     (r1)
   119  	//       v               v
   120  	// ---------------------------------------------------------> time
   121  	//
   122  	// The command on r12 also finishes quickly, at LAI 77.
   123  	//
   124  	//   closed=0,0
   125  	//       |            next=0,1
   126  	//       |          left | right
   127  	//       |             0 # 1
   128  	//       |             1 e 1
   129  	//       |               @ 10     (r1)
   130  	//       |               @ 77     (r12)
   131  	//       v               v
   132  	// ---------------------------------------------------------> time
   133  	//
   134  	// The system closes out a timestamp (registering 1000 as the next timestamp to close out).
   135  	// No problem: nothing is tracked on the left side; returns: 0,1 and map[]
   136  	// Note how the items on the right have moved to the left, as they are relevant for the
   137  	// next call to Close.
   138  	//
   139  	//   closed=0,1
   140  	//       |            next=1.000000000,0
   141  	//       |          left | right
   142  	//       |             1 # 0
   143  	//       |             1 e 1
   144  	//       |            10 @        (r1)
   145  	//       |            77 @        (r12)
   146  	//       v               v
   147  	// ---------------------------------------------------------> time
   148  	//
   149  	// Nothing happens for a while until the system tries to close out the next timestamp.
   150  	// However, the very first proposal is still tracked and blocks progress.
   151  	// The call returns a no-op in the form 0,1 map[] .
   152  	//
   153  	//   closed=0,1
   154  	//       |            next=1.000000000,0
   155  	//       |          left | right
   156  	//       |             1 # 0
   157  	//       |             1 e 1
   158  	//       |            10 @        (r1)
   159  	//       |            77 @        (r12)
   160  	//       v               v
   161  	// ---------------------------------------------------------> time
   162  	//
   163  	// A new command gets tracked on r12 (and is forwarded to 1.000000000,1 (if necessary).
   164  	// It terminates quickly, leaving an MLAI entry of 78 behind.
   165  	//
   166  	//   closed=0,1
   167  	//       |            next=1.000000000,0
   168  	//       |          left | right
   169  	//       |             1 # 0
   170  	//       |             1 e 1
   171  	//       |            10 @        (r1)
   172  	//       |            77 @        (r12)
   173  	//       |               @ 78     (r12)
   174  	//       v               v
   175  	// ---------------------------------------------------------> time
   176  	//
   177  	// Finally! The slow evaluation finishes and the command gets proposed at index 79.
   178  	// Note that the right now tracks a smaller value of 78. Consumers have to keep the
   179  	// maximum they've seen.
   180  	//
   181  	//   closed=0,1
   182  	//       |            next=1.000000000,0
   183  	//       |          left | right
   184  	//       |             0 # 0
   185  	//       |             1 e 1
   186  	//       |            10 @        (r1)
   187  	//       |               @ 78     (r12)
   188  	//       |            79 @        (r12)
   189  	//       v               v
   190  	// ---------------------------------------------------------> time
   191  	//
   192  	// The next call to Close() is successful and returns: 1.000000000,0 and map[1:10 12:79]
   193  	//
   194  	//   closed=1.000000000,0
   195  	//       |            next=3.000000000,0
   196  	//       |          left | right
   197  	//       |             0 # 0
   198  	//       |             1 e 1
   199  	//       |            78 @        (r12)
   200  	//       v               v
   201  	// ---------------------------------------------------------> time
   202  }
   203  
   204  // mlaiString converts an mlai map into a string. Avoids randomized ordering of
   205  // map elements in string output.
   206  func mlaiString(mlai map[roachpb.RangeID]ctpb.LAI) string {
   207  	var rangeIDs []roachpb.RangeID
   208  	for rangeID := range mlai {
   209  		rangeIDs = append(rangeIDs, rangeID)
   210  	}
   211  	sort.Slice(rangeIDs, func(i, j int) bool {
   212  		return rangeIDs[i] < rangeIDs[j]
   213  	})
   214  
   215  	var sb strings.Builder
   216  	sb.WriteString("map[")
   217  	for i, rangeID := range rangeIDs {
   218  		if i > 0 {
   219  			sb.WriteString(" ")
   220  		}
   221  		fmt.Fprintf(&sb, "%d:%d", rangeID, mlai[rangeID])
   222  	}
   223  	sb.WriteString("]")
   224  	return sb.String()
   225  }