# Walk through the basics of the datadriven syntax for range controller handle
# tests.
# 
# A handle in this context is a named RangeController, which is used to simulate
# token deduction and return.
#
# Initialize testing components, including a named handle h.
init
handle=h
----

# Connect the handle to three replication streams (like the leader+leaseholder
# for a triply replicated range would).
# - Start writing to the range at 2MiB/s across 10 reqs/s. 
# - Grab s1 snapshots at t=2 and t=3, to compare how things evolve.
# - Partway through, at t=4s, disconnect s2. 
# - From t=[10s,18s), start returning tokens from s1 and s3.
# - Grab s1 snapshots at t=16s, t=17s and t=19s to compare how things evolve.
# - Start writing to the range again at t=[20s,21s) at 2MiB/s across 10 reqs/s. 
# - At t=22s, close the handle. 
timeline
t=0s        handle=h op=connect    stream=t1/s1
t=0s        handle=h op=connect    stream=t1/s2
t=0s        handle=h op=connect    stream=t1/s3
t=2s        handle=h op=snapshot   stream=t1/s1
t=3s        handle=h op=snapshot   stream=t1/s1
t=4s        handle=h op=disconnect stream=t1/s2
t=[0s,8s)   handle=h class=regular adjust=-2MiB/s rate=10/s
t=[10s,18s) handle=h class=regular adjust=+2MiB/s rate=10/s stream=t1/s1
t=[10s,18s) handle=h class=regular adjust=+2MiB/s rate=10/s stream=t1/s3
t=16s       handle=h op=snapshot   stream=t1/s1
t=17s       handle=h op=snapshot   stream=t1/s1
t=19s       handle=h op=snapshot   stream=t1/s1
t=[20s,24s) handle=h class=regular adjust=-2MiB/s rate=10/s
t=21s       handle=h op=snapshot   stream=t1/s1
t=25s       handle=h op=close
----


simulate t=[0s,28s)
----

# We should observe a few things.
# - We've lazily instantiated three streams for regular traffic. Even when the
#   handle disconnects the stream from itself, it's still tracked by the
#   controller.
#   - Given there are three streams, we start off with 3*16MiB = 48MiB of
#     regular tokens.
#   - When three streams are connected, quorum writes at 2MiB/s translates to
#     token deductions at 3*2MiB/s = 6MiB/s. 
# - When s2 is disconnected from h:
#   - All s2-specific flow tokens deducted by h are returned. By t=4s, this
#     translates to 4s * 2MiB/s = 8MiB. We see this in both
#     regular_tokens_available and the 8MiB/s spike in
#     rate(regular_tokens_returned).
#   - The rate of token deductions decreases to 2*2MiB/s = 4MiB/s.
# - By the time quorum writes are blocked, the available regular tokens is
#   16MiB, corresponding to s2's fully available regular tokens.
plot t=[0s,10s)
kvflowcontrol.streams.eval.regular.total_count        unit=streams
kvflowcontrol.tokens.eval.regular.available           unit=MiB
kvflowcontrol.tokens.eval.regular.{deducted,returned} unit=MiB/s rate=true
----
----
 3.0 ┼───────────────────────────────────────
      streams.eval.regular.total_count (streams)


 47.4 ┼╮
 45.3 ┤╰╮
 43.2 ┤ ╰╮
 41.1 ┤  ╰─╮
 39.0 ┤    ╰╮
 36.9 ┤     ╰─╮
 34.8 ┤       ╰╮
 32.7 ┤        ╰╮
 30.7 ┤         ╰─╮   ╭╮
 28.6 ┤           ╰╮  │╰──╮
 26.5 ┤            ╰╮ │   ╰─╮
 24.4 ┤             ╰─╯     ╰─╮
 22.3 ┤                       ╰─╮
 20.2 ┤                         ╰─╮
 18.1 ┤                           ╰─╮
 16.0 ┤                             ╰─────────
         tokens.eval.regular.available (MiB)


 8.0 ┤               ╭───╮
 7.5 ┤               │   │
 6.9 ┤               │   │
 6.4 ┤               │   │
 5.9 ┤   ╭───────────│╮  │
 5.3 ┤   │           │╰╮ │
 4.8 ┤   │           │ ╰╮│
 4.3 ┤   │           │  ╰│───────────╮
 3.7 ┤   │           │   │           │
 3.2 ┤   │           │   │           ╰╮
 2.7 ┤   │           │   │            │
 2.1 ┤   │           │   │            ╰╮
 1.6 ┤   │           │   │             │
 1.1 ┤   │           │   │             ╰╮
 0.5 ┤   │           │   │              │
 0.0 ┼───────────────╯   ╰───────────────────
      rate(tokens.eval.regular.{deducted,returned}) (MiB/s)
----
----


# This period corresponds to:
#   t=[20s,24s) handle=h class=regular adjust=-2MiB/s rate=10/s
#   t=25s       handle=h op=close
# Where the handle is connected to t1/s1 and t1/s3. Note how when the handle is
# closed, all (2+2)MiB/s*4s = 16MiB tokens for s1 and s3 are returned.
#
# NB: There's some degree of smoothing happening in the rate plots below, which
# is why we see a slow ascent/descent to/from 4MiB/s.
plot t=[19s,28s)
kvflowcontrol.tokens.eval.regular.available           unit=MiB
kvflowcontrol.tokens.eval.regular.{deducted,returned} unit=MiB/s rate=true
----
----
 48.0 ┼────╮                     ╭────────────
 46.9 ┤    ╰╮                    │
 45.9 ┤     ╰╮                   │
 44.8 ┤      ╰─╮                 │
 43.7 ┤        ╰╮                │
 42.7 ┤         ╰╮               │
 41.6 ┤          ╰╮              │
 40.5 ┤           ╰╮             │
 39.5 ┤            ╰╮            │
 38.4 ┤             ╰─╮          │
 37.3 ┤               ╰╮        ╭╯
 36.3 ┤                ╰╮       │
 35.2 ┤                 ╰╮      │
 34.1 ┤                  ╰╮     │
 33.1 ┤                   ╰╮    │
 32.0 ┤                    ╰────╯
         tokens.eval.regular.available (MiB)


 16.0 ┤                          ╭───╮
 14.9 ┤                          │   │
 13.9 ┤                          │   │
 12.8 ┤                          │   │
 11.7 ┤                          │   │
 10.7 ┤                          │   │
  9.6 ┤                          │   │
  8.5 ┤                          │   │
  7.5 ┤                          │   │
  6.4 ┤                          │   │
  5.3 ┤                         ╭╯   │
  4.3 ┤        ╭────────────╮   │    │
  3.2 ┤      ╭─╯            ╰╮  │    │
  2.1 ┤     ╭╯               ╰─╮│    │
  1.1 ┤    ╭╯                  ╰│    │
  0.0 ┼─────────────────────────╯────╰────────
       rate(tokens.eval.regular.{deducted,returned}) (MiB/s)
----
----

# Observe captured snapshots.
# - At 10 reqs/s, by t=2s we have 10*2=20 tracked tokens from log positions
#   4/1 to 4/20. We add 10 more by t=3s, going up to 4/30.
# - At t=16s the we're tracking tokens from log positions 4/62 to 4/80. We
#   return tokens in 10 increments of 205KiB over the next second, so at t=17s
#   we've reduced the remaining tracked tokens by 10, now starting at 4/62.
# - At t=19s we have no outstanding tokens being tracked -- we've returned
#   everything.
# - At t=21s we've tracked a few more tokens; tokens we haven't returned yet.
#
# TODO(kvoli,sumeerbhola): Support filtering this output by stream and time
# range.
snapshots handle=h
----
----
t=2s stream=t1/s1
 pri=normal-pri
  tokens=205KiB log-position=1/1
  tokens=205KiB log-position=1/2
  tokens=205KiB log-position=1/3
  tokens=205KiB log-position=1/4
  tokens=205KiB log-position=1/5
  tokens=205KiB log-position=1/6
  tokens=205KiB log-position=1/7
  tokens=205KiB log-position=1/8
  tokens=205KiB log-position=1/9
  tokens=205KiB log-position=1/10
  tokens=205KiB log-position=1/11
  tokens=205KiB log-position=1/12
  tokens=205KiB log-position=1/13
  tokens=205KiB log-position=1/14
  tokens=205KiB log-position=1/15
  tokens=205KiB log-position=1/16
  tokens=205KiB log-position=1/17
  tokens=205KiB log-position=1/18
  tokens=205KiB log-position=1/19
  tokens=205KiB log-position=1/20

t=3s stream=t1/s1
 pri=normal-pri
  tokens=205KiB log-position=1/1
  tokens=205KiB log-position=1/2
  tokens=205KiB log-position=1/3
  tokens=205KiB log-position=1/4
  tokens=205KiB log-position=1/5
  tokens=205KiB log-position=1/6
  tokens=205KiB log-position=1/7
  tokens=205KiB log-position=1/8
  tokens=205KiB log-position=1/9
  tokens=205KiB log-position=1/10
  tokens=205KiB log-position=1/11
  tokens=205KiB log-position=1/12
  tokens=205KiB log-position=1/13
  tokens=205KiB log-position=1/14
  tokens=205KiB log-position=1/15
  tokens=205KiB log-position=1/16
  tokens=205KiB log-position=1/17
  tokens=205KiB log-position=1/18
  tokens=205KiB log-position=1/19
  tokens=205KiB log-position=1/20
  tokens=205KiB log-position=1/21
  tokens=205KiB log-position=1/22
  tokens=205KiB log-position=1/23
  tokens=205KiB log-position=1/24
  tokens=205KiB log-position=1/25
  tokens=205KiB log-position=1/26
  tokens=205KiB log-position=1/27
  tokens=205KiB log-position=1/28
  tokens=205KiB log-position=1/29
  tokens=205KiB log-position=1/30

t=16s stream=t1/s1
 pri=normal-pri
  tokens=205KiB log-position=1/62
  tokens=205KiB log-position=1/63
  tokens=205KiB log-position=1/64
  tokens=205KiB log-position=1/65
  tokens=205KiB log-position=1/66
  tokens=205KiB log-position=1/67
  tokens=205KiB log-position=1/68
  tokens=205KiB log-position=1/69
  tokens=205KiB log-position=1/70
  tokens=205KiB log-position=1/71
  tokens=205KiB log-position=1/72
  tokens=205KiB log-position=1/73
  tokens=205KiB log-position=1/74
  tokens=205KiB log-position=1/75
  tokens=205KiB log-position=1/76
  tokens=205KiB log-position=1/77
  tokens=205KiB log-position=1/78
  tokens=205KiB log-position=1/79
  tokens=205KiB log-position=1/80

t=17s stream=t1/s1
 pri=normal-pri
  tokens=205KiB log-position=1/72
  tokens=205KiB log-position=1/73
  tokens=205KiB log-position=1/74
  tokens=205KiB log-position=1/75
  tokens=205KiB log-position=1/76
  tokens=205KiB log-position=1/77
  tokens=205KiB log-position=1/78
  tokens=205KiB log-position=1/79
  tokens=205KiB log-position=1/80

t=19s stream=t1/s1
 
t=21s stream=t1/s1
 pri=normal-pri
  tokens=205KiB log-position=1/81
  tokens=205KiB log-position=1/82
  tokens=205KiB log-position=1/83
  tokens=205KiB log-position=1/84
  tokens=205KiB log-position=1/85
  tokens=205KiB log-position=1/86
  tokens=205KiB log-position=1/87
  tokens=205KiB log-position=1/88
  tokens=205KiB log-position=1/89
  tokens=205KiB log-position=1/90
  tokens=205KiB log-position=1/91
----
----

# vim:ft=conf
