Repository: argoproj-labs/old-argo-dataflow (language: python)

Issue:
Expression based scaling
Expression will allow complex scaling. This issue replaces:

* https://github.com/argoproj-labs/argo-dataflow/issues/242
* https://github.com/argoproj-labs/argo-dataflow/issues/243
* https://github.com/argoproj-labs/argo-dataflow/issues/244

There are two equation (semantics? formula? expression?) we currently use, which we need parity:

* **What** the target number of replicas is: `desiredReplicas`
* **When** to next to test where or not to scale.: `scalingDelay`.
* **When** to next peek: `peekDelay` 

Expressions are evaluated within an "expression environment", i.e. some variables.

* Time since last scale `time.Since(lastScaledAt)`
* How many pending messages there are: `pending`

And some constants:

* Replica ratio:  `spec.scale.ratio`
* Min replicas:  `spec.scale.minReplicas`
* Max replicas (optional):  `spec.scale.maxReplicas`
* Default scaling delay (1m):  `ARGO_DATAFLOW_SCALING_DELAY`
* Default peek delay (4m) `ARGO_DATAFLOW_PEEK_DELAY`

Things not currently factored, but could be added:

* Pending rate
* CPU or memory usage (I.e. like HPA ;) )


Discussion / hints:

Fix patch:
diff --git a/api/v1alpha1/generated.pb.go b/api/v1alpha1/generated.pb.go
index 4e666fe4..2cefe22b 100644
--- a/api/v1alpha1/generated.pb.go
+++ b/api/v1alpha1/generated.pb.go
@@ -1932,272 +1932,273 @@ func init() {
 }
 
 var fileDescriptor_7a4218a80d7ff35f = []byte{
-	// 4229 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x4d, 0x6c, 0x23, 0x47,
-	0x76, 0x76, 0xf3, 0x47, 0x24, 0x1f, 0x25, 0x8d, 0xa6, 0x6c, 0x64, 0xb9, 0x8a, 0x2d, 0x0d, 0x7a,
-	0xe3, 0xcd, 0x6c, 0x60, 0x53, 0xb6, 0xc7, 0x46, 0x66, 0xd6, 0xf1, 0xda, 0x24, 0xa5, 0x19, 0x6b,
-	0x87, 0xd2, 0x68, 0xaa, 0xa5, 0x99, 0x38, 0xf6, 0x66, 0x52, 0xea, 0x2e, 0x92, 0x3d, 0x6a, 0x76,
-	0x73, 0xba, 0x8b, 0xf2, 0x28, 0xa7, 0xc5, 0xe6, 0x07, 0xc8, 0x21, 0x40, 0x72, 0xc8, 0x2d, 0x97,
-	0x1c, 0x36, 0x01, 0x12, 0x04, 0x01, 0x82, 0x1c, 0xb2, 0x17, 0x5f, 0x72, 0x88, 0x8f, 0x06, 0xf6,
-	0x62, 0x6c, 0x00, 0x61, 0xad, 0xcd, 0x29, 0xc7, 0x1c, 0x72, 0xd0, 0x29, 0xa8, 0xbf, 0xee, 0x6a,
-	0x4a, 0xb3, 0x2b, 0x91, 0xde, 0x39, 0x89, 0xfd, 0xde, 0xab, 0xef, 0xd5, 0xcf, 0xab, 0x57, 0xef,
-	0xbd, 0x2a, 0x41, 0xa7, 0xef, 0xb3, 0xc1, 0x78, 0xbf, 0xe9, 0x46, 0xc3, 0x35, 0x12, 0xf7, 0xa3,
-	0x51, 0x1c, 0x3d, 0x7e, 0x3d, 0x20, 0xfb, 0x89, 0xf8, 0x7a, 0xdd, 0x23, 0x8c, 0xf4, 0x82, 0xe8,
-	0xd3, 0x35, 0x32, 0xf2, 0xd7, 0x0e, 0xdf, 0x24, 0xc1, 0x68, 0x40, 0xde, 0x5c, 0xeb, 0xd3, 0x90,
-	0xc6, 0x84, 0x51, 0xaf, 0x39, 0x8a, 0x23, 0x16, 0xa1, 0x1b, 0x19, 0x48, 0x53, 0x83, 0x3c, 0xe2,
-	0x20, 0xe2, 0xeb, 0x91, 0x06, 0x69, 0x92, 0x91, 0xdf, 0xd4, 0x20, 0xcb, 0xaf, 0x1b, 0x9a, 0xfb,
-	0x51, 0x3f, 0x5a, 0x13, 0x58, 0xfb, 0xe3, 0x9e, 0xf8, 0x12, 0x1f, 0xe2, 0x97, 0xd4, 0xb1, 0x6c,
-	0x1f, 0xdc, 0x4c, 0x9a, 0x7e, 0x24, 0x3a, 0xe2, 0x46, 0x31, 0x5d, 0x3b, 0x3c, 0xd3, 0x8f, 0xe5,
-	0xb7, 0x33, 0x99, 0x21, 0x71, 0x07, 0x7e, 0x48, 0xe3, 0xa3, 0xb5, 0xd1, 0x41, 0x5f, 0x34, 0x8a,
-	0x69, 0x12, 0x8d, 0x63, 0x97, 0x5e, 0xaa, 0x55, 0xb2, 0x36, 0xa4, 0x8c, 0x9c, 0xa3, 0xcb, 0xfe,
-	0xd2, 0x82, 0xc5, 0xd6, 0x43, 0xa7, 0x13, 0x53, 0x8f, 0x86, 0xcc, 0x27, 0x41, 0x82, 0x3e, 0x81,
-	0x3a, 0x71, 0x5d, 0x9a, 0x24, 0x77, 0xe9, 0xd1, 0xa6, 0xd7, 0xb0, 0xae, 0x59, 0xd7, 0xeb, 0x6f,
-	0xbd, 0xda, 0x94, 0xf0, 0x62, 0xf0, 0xbc, 0xe3, 0xcd, 0xc3, 0x37, 0x9b, 0x0e, 0x75, 0x63, 0xca,
-	0xee, 0xd2, 0x23, 0x87, 0x06, 0xd4, 0x65, 0x51, 0xdc, 0x7e, 0xf1, 0xf3, 0xe3, 0xd5, 0x17, 0x4e,
-	0x8e, 0x57, 0xeb, 0xad, 0x14, 0x61, 0x1d, 0x9b, 0x70, 0x68, 0x00, 0x57, 0x12, 0xd1, 0x2c, 0x95,
-	0x68, 0x14, 0x2e, 0xa3, 0xe1, 0x1b, 0x4a, 0xc3, 0x15, 0x27, 0x8f, 0x82, 0x27, 0x61, 0xed, 0xd7,
-	0xa0, 0xde, 0x7a, 0xe8, 0x6c, 0x84, 0xde, 0x28, 0xf2, 0x43, 0x86, 0x5e, 0x81, 0xe2, 0x38, 0x0e,
-	0xc4, 0x70, 0x6a, 0xed, 0xba, 0x42, 0x29, 0xee, 0xe1, 0x2e, 0xe6, 0x74, 0xfb, 0xa7, 0x05, 0xa8,
-	0xb4, 0x89, 0x7b, 0x10, 0xf5, 0x7a, 0xe8, 0x13, 0xa8, 0x7a, 0xe3, 0x98, 0x30, 0x3f, 0x0a, 0x1b,
-	0x25, 0xd1, 0xb9, 0xa6, 0xd1, 0xb9, 0x74, 0x76, 0x9b, 0xa3, 0x83, 0x3e, 0x27, 0x24, 0x4d, 0x3e,
-	0xbb, 0xbc, 0xbb, 0xeb, 0xaa, 0x55, 0x7b, 0x49, 0xe1, 0x57, 0x35, 0x05, 0xa7, 0x88, 0xe8, 0x0d,
-	0x58, 0xba, 0x4d, 0xf8, 0x58, 0x76, 0x68, 0xec, 0xd2, 0x90, 0x91, 0x3e, 0x6d, 0x94, 0xaf, 0x59,
-	0xd7, 0x17, 0xda, 0x25, 0xde, 0x0a, 0x9f, 0xe1, 0xa2, 0x6f, 0x41, 0x39, 0x61, 0x74, 0x94, 0x88,
-	0xce, 0x97, 0xda, 0x0b, 0x0a, 0xbc, 0xec, 0x70, 0x22, 0x96, 0x3c, 0xb4, 0x05, 0x45, 0x97, 0x8c,
-	0xd4, 0x64, 0x5e, 0xb6, 0xbf, 0xe9, 0x7c, 0x74, 0xc8, 0x08, 0x73, 0x1c, 0xb4, 0x0e, 0x4b, 0x8f,
-	0x7d, 0xc6, 0xa8, 0xd9, 0xcb, 0xa2, 0xe8, 0x65, 0x43, 0xc9, 0x2e, 0x7d, 0x7f, 0x82, 0x8f, 0xcf,
-	0xb4, 0xb0, 0xcb, 0x50, 0xec, 0x10, 0x66, 0x7b, 0x50, 0xea, 0x44, 0x1e, 0x45, 0x6f, 0x43, 0x25,
-	0x1e, 0x87, 0xcc, 0x1f, 0x52, 0x31, 0xaf, 0xb5, 0xf6, 0xb2, 0xc2, 0xaa, 0x60, 0x49, 0x3e, 0xcd,
-	0x7e, 0x62, 0x2d, 0x8a, 0xbe, 0x0d, 0x73, 0xd2, 0xe6, 0x45, 0x07, 0x6a, 0xed, 0x45, 0xd5, 0x68,
-	0xce, 0x11, 0x54, 0xac, 0xb8, 0xf6, 0x67, 0x45, 0xa8, 0x75, 0xa2, 0x90, 0x11, 0x3e, 0x5a, 0x3e,
-	0x69, 0xfe, 0x90, 0xf7, 0x5a, 0xae, 0x78, 0x3a, 0x69, 0x9b, 0x9c, 0x88, 0x25, 0x0f, 0x7d, 0x04,
-	0xf3, 0x87, 0x51, 0x30, 0x1e, 0xd2, 0xad, 0x68, 0x1c, 0xb2, 0xa4, 0x51, 0xbe, 0x56, 0xbc, 0x5e,
-	0x7f, 0x6b, 0xf5, 0x3c, 0x53, 0x7c, 0x90, 0xc9, 0xb5, 0x5f, 0x52, 0x60, 0xf3, 0x06, 0x31, 0xc1,
-	0x39, 0x28, 0xf4, 0x00, 0x0a, 0x7e, 0x28, 0x7a, 0x5c, 0x7f, 0xeb, 0x7b, 0xcd, 0x29, 0x5c, 0x4b,
-	0x73, 0x33, 0x64, 0x34, 0xee, 0x11, 0x97, 0xb6, 0xe7, 0x4e, 0x8e, 0x57, 0x0b, 0x9b, 0x21, 0x2e,
-	0xf8, 0x21, 0x7a, 0x15, 0x2a, 0x6e, 0x34, 0x1c, 0x92, 0xd0, 0x6b, 0xcc, 0x5d, 0x2b, 0x72, 0x5b,
-	0xe6, 0xf3, 0xd7, 0x91, 0x24, 0xac, 0x79, 0xe8, 0x65, 0x28, 0x91, 0xb8, 0x9f, 0x34, 0x2a, 0x42,
-	0xa6, 0x7a, 0x72, 0xbc, 0x5a, 0x6a, 0xc5, 0xfd, 0x04, 0x0b, 0x2a, 0xba, 0x05, 0x45, 0x1a, 0x1e,
-	0x36, 0xaa, 0x62, 0xb8, 0xcb, 0xe7, 0x0d, 0x77, 0x23, 0x3c, 0x7c, 0x40, 0xe2, 0xcc, 0x30, 0x36,
-	0xc2, 0x43, 0xcc, 0xdb, 0xa0, 0x8f, 0xa0, 0xa6, 0x7d, 0x50, 0xd2, 0xa8, 0x89, 0xe1, 0x5d, 0x3f,
-	0x0f, 0x00, 0x2b, 0x21, 0x4c, 0x9f, 0x8c, 0xfd, 0x98, 0x0e, 0x69, 0xc8, 0x92, 0xf6, 0x55, 0x05,
-	0x57, 0xd3, 0xdc, 0x04, 0x67, 0x68, 0xf6, 0x27, 0x50, 0xea, 0xc4, 0x51, 0x88, 0x5e, 0x83, 0x6a,
-	0xe2, 0x0e, 0xa8, 0x37, 0x0e, 0xf4, 0xea, 0xa5, 0xfb, 0xc9, 0x51, 0x74, 0x9c, 0x4a, 0x70, 0xf3,
-	0x08, 0xc8, 0x51, 0x34, 0x66, 0xc2, 0xf6, 0x0d, 0xf3, 0xe8, 0x0a, 0x2a, 0x56, 0x5c, 0xfb, 0x1f,
-	0x2c, 0x98, 0x5f, 0x6f, 0xaf, 0x13, 0x46, 0xa4, 0xdd, 0x70, 0x0b, 0x39, 0x24, 0xc1, 0xf8, 0x8c,
-	0x85, 0x3c, 0xe0, 0x44, 0x2c, 0x79, 0x28, 0x86, 0x9a, 0xf8, 0x71, 0x3b, 0x8e, 0x86, 0x6a, 0x73,
-	0x6d, 0x4c, 0xb5, 0x9a, 0xa6, 0x6a, 0x0e, 0xd6, 0x5e, 0xe0, 0xf3, 0xf0, 0x40, 0x63, 0xe3, 0x4c,
-	0x8d, 0x1d, 0xc1, 0xd2, 0xa4, 0x34, 0xfa, 0x18, 0xe6, 0x13, 0xed, 0x0c, 0x31, 0xed, 0x5d, 0xce,
-	0x2d, 0x2f, 0x71, 0x5b, 0x75, 0x8c, 0xe6, 0x38, 0x07, 0x66, 0xff, 0xdc, 0x82, 0xb9, 0xf5, 0xb6,
-	0xe3, 0x87, 0x07, 0xe8, 0x00, 0xaa, 0xbc, 0xff, 0xfb, 0x24, 0xa1, 0x4a, 0xc7, 0x7b, 0xd3, 0x0d,
-	0x57, 0x81, 0x18, 0xae, 0x50, 0x51, 0x70, 0xaa, 0x00, 0xf9, 0x50, 0x21, 0x2e, 0x77, 0x40, 0x49,
-	0xa3, 0x20, 0x4c, 0x71, 0xba, 0x8d, 0xe2, 0xdc, 0xef, 0xb6, 0x04, 0x4c, 0xfb, 0x8a, 0xf6, 0x27,
-	0xf2, 0x3b, 0xc1, 0x1a, 0xdf, 0xfe, 0xef, 0x22, 0x54, 0xd7, 0xdb, 0x6a, 0xe5, 0x9f, 0xeb, 0x20,
-	0xbf, 0x05, 0xe5, 0x27, 0x63, 0x1a, 0x1f, 0x29, 0xf3, 0x4c, 0xcd, 0xec, 0x3e, 0x27, 0x62, 0xc9,
-	0x43, 0x37, 0x61, 0x3e, 0xea, 0xf5, 0x12, 0xca, 0x3a, 0xdc, 0x87, 0x84, 0xca, 0xd3, 0xa5, 0x7e,
-	0xe6, 0x9e, 0xc1, 0xc3, 0x39, 0x49, 0x34, 0x80, 0xf9, 0x51, 0x14, 0x04, 0xc2, 0x59, 0x1c, 0x92,
-	0x60, 0xca, 0x03, 0x2b, 0xd5, 0xb4, 0x63, 0x60, 0xe1, 0x1c, 0x32, 0x0a, 0x61, 0x91, 0x7b, 0x17,
-	0x9f, 0xa5, 0xba, 0xca, 0x53, 0xe9, 0xfa, 0x0d, 0xa5, 0x6b, 0xb1, 0x93, 0x43, 0xc3, 0x13, 0xe8,
-	0xe8, 0x2d, 0x00, 0x3f, 0xf4, 0x19, 0xdf, 0xf2, 0x43, 0xd2, 0x98, 0xbb, 0x66, 0x5d, 0xaf, 0xb6,
-	0x91, 0x6a, 0x0b, 0x9b, 0x29, 0x07, 0x1b, 0x52, 0xf6, 0x8f, 0x2d, 0x48, 0xd7, 0x80, 0x7b, 0x06,
-	0x2f, 0xf6, 0x0f, 0x69, 0xac, 0x76, 0x78, 0xea, 0x19, 0xd6, 0x05, 0x15, 0x2b, 0x2e, 0x7a, 0x02,
-	0xe0, 0xa5, 0xbb, 0x4d, 0x6d, 0xf2, 0xd6, 0xcc, 0x9b, 0xbc, 0xbd, 0xc8, 0xfb, 0x99, 0x7d, 0x63,
-	0x43, 0x89, 0xfd, 0x23, 0xbe, 0xe3, 0xa8, 0x37, 0x1e, 0x51, 0x11, 0x98, 0xf8, 0xde, 0x99, 0xc0,
-	0x64, 0x73, 0x1d, 0x73, 0x3a, 0xfa, 0x08, 0x2a, 0x43, 0xf2, 0xd4, 0xf1, 0xff, 0x98, 0x5e, 0xe4,
-	0x6c, 0x6f, 0x6a, 0x6f, 0xda, 0xbc, 0x3f, 0x26, 0x21, 0xf3, 0xd9, 0x51, 0xb6, 0x27, 0xb6, 0x24,
-	0x0c, 0xd6, 0x78, 0x76, 0x15, 0xe6, 0x36, 0x9e, 0x8e, 0x48, 0xe8, 0xd9, 0x35, 0xa8, 0xdc, 0x0e,
-	0x08, 0x63, 0x34, 0xb4, 0x7f, 0x31, 0x07, 0x0b, 0x77, 0x28, 0xdb, 0x89, 0x3c, 0x67, 0x44, 0x5d,
-	0x4c, 0x9f, 0xa0, 0x77, 0xa0, 0xee, 0x06, 0xe3, 0x84, 0xd1, 0x78, 0x9b, 0x0c, 0xa9, 0xf0, 0xf9,
-	0xb5, 0x2c, 0xd2, 0xeb, 0x64, 0x2c, 0x6c, 0xca, 0x71, 0xbb, 0xf7, 0xe8, 0xfe, 0xb8, 0xdf, 0x98,
-	0x17, 0x2b, 0x97, 0xda, 0xfd, 0x3a, 0x27, 0x62, 0xc9, 0xe3, 0x76, 0x3f, 0xf2, 0x47, 0x34, 0xf0,
-	0x43, 0x2a, 0xc0, 0xad, 0xbc, 0xdd, 0xef, 0x18, 0x3c, 0x9c, 0x93, 0x44, 0x6b, 0x50, 0x0b, 0xc9,
-	0x90, 0x26, 0x23, 0xa2, 0xd6, 0xac, 0x96, 0x9d, 0x2e, 0xdb, 0x9a, 0x81, 0x33, 0x19, 0xf4, 0x1d,
-	0xa8, 0xc4, 0x74, 0x14, 0xf8, 0x2e, 0x11, 0xbb, 0xab, 0x9c, 0x4d, 0x0c, 0x96, 0x64, 0xac, 0xf9,
-	0x7c, 0xc4, 0x22, 0x3e, 0xb8, 0x1d, 0xc5, 0x43, 0xc2, 0x54, 0xac, 0x92, 0x8e, 0x78, 0x33, 0x63,
-	0x61, 0x53, 0x8e, 0x37, 0x8b, 0xc7, 0x61, 0x48, 0x63, 0x21, 0x21, 0x76, 0x87, 0xd1, 0x0c, 0x67,
-	0x2c, 0x6c, 0xca, 0x21, 0x07, 0x60, 0x34, 0x0e, 0x82, 0x9d, 0x28, 0xf0, 0xdd, 0x23, 0x61, 0xe7,
-	0xb5, 0xf6, 0x0d, 0x6d, 0xe7, 0x3b, 0x29, 0xe7, 0xf4, 0x78, 0xf5, 0x95, 0xb3, 0xd9, 0x43, 0x33,
-	0x13, 0xc0, 0x06, 0x0c, 0xba, 0x07, 0x8b, 0xe3, 0x91, 0x47, 0x18, 0x4d, 0x37, 0x6b, 0xe5, 0x9a,
-	0x75, 0xbd, 0xd8, 0xfe, 0x6d, 0xbd, 0xf9, 0xf6, 0x72, 0xdc, 0xd3, 0xe3, 0xd5, 0x05, 0x1e, 0x6c,
-	0xa5, 0xbb, 0x14, 0x4f, 0x34, 0x47, 0x09, 0x00, 0x0f, 0x34, 0x1d, 0x46, 0xd8, 0x38, 0x69, 0x54,
-	0x85, 0x29, 0xbe, 0x3f, 0x9d, 0xbb, 0x4e, 0x61, 0xb2, 0xed, 0x9c, 0xd1, 0xb0, 0xa1, 0x06, 0xf5,
-	0xa1, 0x92, 0xf8, 0x1e, 0x75, 0x49, 0xdc, 0x00, 0xa1, 0xf1, 0xf7, 0xa6, 0xd3, 0x28, 0x31, 0xb2,
-	0x15, 0x57, 0x04, 0xac, 0xd1, 0x51, 0x08, 0x4b, 0x62, 0x25, 0xf9, 0x6c, 0xca, 0x83, 0x32, 0x69,
-	0xd4, 0xc5, 0x91, 0x74, 0x6e, 0x70, 0xd3, 0x8d, 0x5c, 0x12, 0xdc, 0xdb, 0x7f, 0x4c, 0x5d, 0x86,
-	0x69, 0x8f, 0xc6, 0x34, 0x74, 0x69, 0x16, 0x18, 0x6f, 0x4e, 0x20, 0xe1, 0x33, 0xd8, 0xf6, 0x3f,
-	0x97, 0xa0, 0x78, 0xc7, 0x67, 0x17, 0x8b, 0x52, 0x2f, 0x18, 0xf2, 0xa9, 0x0c, 0xa7, 0x70, 0x7e,
-	0x86, 0x83, 0x08, 0x2c, 0x8e, 0x13, 0x1a, 0xf3, 0x0d, 0x21, 0x7b, 0x21, 0x2c, 0xe2, 0xc2, 0x31,
-	0x04, 0x12, 0x46, 0x93, 0x03, 0xc0, 0x13, 0x80, 0x5c, 0xc5, 0x88, 0x24, 0xc9, 0xa7, 0x51, 0xec,
-	0x29, 0x15, 0xd5, 0x4b, 0xab, 0xd8, 0xc9, 0x01, 0xe0, 0x09, 0x40, 0x34, 0x82, 0x17, 0x93, 0x64,
-	0xb0, 0x13, 0xfb, 0x87, 0x84, 0x51, 0xd1, 0x58, 0xe8, 0xa9, 0x5d, 0x2a, 0x87, 0x3c, 0x39, 0x5e,
-	0x7d, 0xd1, 0x71, 0x3e, 0x9c, 0x44, 0xc1, 0xe7, 0x41, 0xa3, 0x6b, 0x50, 0x1a, 0x11, 0x36, 0x50,
-	0x47, 0xf2, 0xbc, 0x9a, 0xd7, 0xd2, 0x0e, 0x61, 0x03, 0x2c, 0x38, 0xfc, 0x9c, 0xd9, 0x8f, 0x49,
-	0xe8, 0x0e, 0x94, 0xa7, 0x48, 0xcf, 0x99, 0xb6, 0xa0, 0x62, 0xc5, 0xd5, 0x51, 0x77, 0xf9, 0xf2,
-	0x51, 0xb7, 0xfd, 0x7f, 0x16, 0x94, 0xef, 0xc4, 0xd1, 0x78, 0xc4, 0x57, 0xf9, 0x80, 0x1e, 0x4d,
-	0x1e, 0x17, 0x3c, 0x90, 0xe3, 0x74, 0x7e, 0x68, 0xd2, 0xd0, 0xbb, 0xd7, 0x13, 0xc2, 0xca, 0x16,
-	0xd2, 0x5d, 0xb6, 0x91, 0x72, 0xb0, 0x21, 0x85, 0xde, 0x81, 0xb9, 0x9e, 0xf4, 0x74, 0x72, 0x8c,
-	0xaf, 0xe8, 0xfe, 0x4b, 0xbf, 0x76, 0x7a, 0xbc, 0x5a, 0x17, 0x82, 0xca, 0xe7, 0x29, 0x61, 0xe4,
-	0x42, 0x25, 0x61, 0x51, 0xcc, 0xad, 0xb7, 0x34, 0xcb, 0xe6, 0x94, 0x18, 0xd2, 0xa8, 0xd5, 0x07,
-	0xd6, 0xc8, 0xf6, 0x1c, 0x94, 0x3e, 0xdc, 0xdd, 0xdd, 0xb1, 0xff, 0xd3, 0x02, 0xe0, 0x3f, 0x3e,
-	0xa4, 0xc4, 0xa3, 0x31, 0x5f, 0x94, 0x30, 0x3b, 0x2f, 0xd2, 0x45, 0x11, 0xe7, 0x84, 0xe0, 0x64,
-	0xd1, 0x7d, 0xe1, 0xa2, 0xd1, 0x7d, 0x71, 0x86, 0xe8, 0x3e, 0xeb, 0x9a, 0x3a, 0xfc, 0x9f, 0x1d,
-	0xdd, 0x27, 0xb0, 0x34, 0x29, 0x8d, 0x1e, 0xcd, 0x12, 0xdd, 0xa7, 0xa7, 0xe5, 0x2f, 0x89, 0xf0,
-	0xff, 0xc6, 0x82, 0x2a, 0xd7, 0x2a, 0x62, 0xfc, 0x5f, 0x5e, 0x0a, 0x41, 0x8f, 0xa1, 0x32, 0x10,
-	0x9d, 0xd3, 0x51, 0xf9, 0xfb, 0x33, 0x4e, 0x49, 0xe6, 0x77, 0xe5, 0x77, 0x82, 0xb5, 0x02, 0xbb,
-	0x23, 0x57, 0x55, 0x4d, 0xc3, 0x3b, 0x50, 0x4f, 0x68, 0x7c, 0xe8, 0xbb, 0x66, 0x30, 0x90, 0x1e,
-	0xa0, 0x4e, 0xc6, 0xc2, 0xa6, 0x9c, 0xfd, 0xe7, 0x16, 0xd4, 0xd2, 0x64, 0x99, 0x9b, 0x46, 0xcf,
-	0xef, 0x45, 0xa2, 0x75, 0x35, 0x33, 0x8d, 0xdb, 0x9b, 0xb7, 0xef, 0x61, 0xc1, 0x41, 0x0f, 0xa1,
-	0x34, 0x60, 0x4c, 0xd7, 0x4a, 0x6e, 0x4d, 0x3d, 0x3a, 0x99, 0x56, 0xf3, 0x5f, 0x58, 0x00, 0x72,
-	0x23, 0x2d, 0xdf, 0x25, 0xbd, 0x03, 0x72, 0x01, 0xfb, 0xfc, 0x14, 0xea, 0x07, 0x5c, 0xb4, 0x13,
-	0x85, 0x3d, 0xbf, 0xaf, 0x76, 0xd0, 0x07, 0x53, 0xf5, 0xe5, 0x6e, 0x86, 0x93, 0xcd, 0x96, 0x41,
-	0xc4, 0xa6, 0x26, 0xbe, 0x31, 0x58, 0x34, 0xf2, 0x5d, 0xb5, 0xd9, 0xd3, 0x8d, 0xb1, 0xcb, 0x89,
-	0x58, 0xf2, 0xec, 0x9f, 0x58, 0x60, 0x22, 0xf0, 0x23, 0x68, 0x3f, 0x8e, 0x0e, 0xb8, 0x4d, 0x58,
-	0xd9, 0x11, 0xd4, 0x96, 0x24, 0xac, 0x79, 0x3c, 0xc6, 0x3a, 0xa4, 0x71, 0xe2, 0x47, 0xa1, 0xda,
-	0x76, 0xe9, 0xca, 0x3f, 0x90, 0x64, 0xac, 0xf9, 0xe8, 0xf7, 0xa1, 0x18, 0x52, 0xa6, 0x36, 0xdd,
-	0x7b, 0xd3, 0x8f, 0x7b, 0x7b, 0x63, 0xb7, 0x5d, 0xe1, 0xf6, 0xbb, 0xbd, 0xb1, 0x8b, 0x39, 0xa4,
-	0xfd, 0xef, 0x16, 0x54, 0x35, 0x0b, 0x39, 0x50, 0x64, 0x41, 0xa2, 0x36, 0xd4, 0xcd, 0xa9, 0xd4,
-	0xec, 0x76, 0x1d, 0xa9, 0x61, 0xb7, 0xeb, 0x60, 0x8e, 0xc6, 0x0d, 0x28, 0x21, 0x49, 0x30, 0x93,
-	0x01, 0x39, 0x2d, 0xa7, 0x2b, 0x0d, 0x88, 0xff, 0xc2, 0x02, 0xd0, 0xfe, 0x6b, 0x0b, 0x6a, 0xa2,
-	0xeb, 0x62, 0x9f, 0x3e, 0x82, 0xb2, 0x58, 0x38, 0xd5, 0xfb, 0xef, 0x4e, 0x3f, 0x49, 0xd9, 0x2a,
-	0x8b, 0x4f, 0x2c, 0x71, 0xb9, 0x29, 0x90, 0xe4, 0x28, 0x74, 0xc5, 0x40, 0x8c, 0x10, 0xbd, 0xc5,
-	0x89, 0x58, 0xf2, 0xec, 0x7f, 0xd3, 0xa6, 0x90, 0xfa, 0xaa, 0x5f, 0x73, 0xaf, 0xd6, 0xa1, 0x9e,
-	0x30, 0x12, 0x33, 0x99, 0xf4, 0x2a, 0x43, 0xb2, 0x53, 0x2f, 0x90, 0xb1, 0x4e, 0xb5, 0x99, 0xcb,
-	0x4f, 0x6c, 0x36, 0xb3, 0xd7, 0xa0, 0xd8, 0x8d, 0xfa, 0xe8, 0x3a, 0x54, 0x59, 0x3c, 0x0e, 0x5d,
-	0xc2, 0xa8, 0x2a, 0x9f, 0xce, 0xf3, 0x3c, 0x7d, 0x57, 0xd1, 0x70, 0xca, 0xb5, 0x7f, 0x58, 0x84,
-	0xea, 0x16, 0x65, 0x84, 0x77, 0x18, 0xfd, 0x99, 0x05, 0x75, 0x12, 0x86, 0x11, 0x23, 0xb2, 0x3c,
-	0x61, 0x09, 0x47, 0xb8, 0x3d, 0xd5, 0x58, 0x35, 0x68, 0xb3, 0x95, 0x01, 0x6e, 0x84, 0x2c, 0x3e,
-	0x32, 0xca, 0xe5, 0x19, 0x07, 0x9b, 0x7a, 0xd1, 0x13, 0x98, 0x0b, 0xc8, 0x3e, 0x0d, 0xb4, 0x2b,
-	0xde, 0x9c, 0xad, 0x07, 0x5d, 0x81, 0x25, 0x95, 0x1b, 0x75, 0x32, 0x4e, 0xc4, 0x4a, 0xd1, 0xf2,
-	0xf7, 0x60, 0x69, 0xb2, 0xa3, 0x68, 0xc9, 0x08, 0x3a, 0x64, 0x9c, 0xf1, 0x52, 0xee, 0x78, 0x55,
-	0xe7, 0xe9, 0x77, 0x0b, 0x37, 0xad, 0xe5, 0x5b, 0x50, 0x37, 0xd4, 0x5c, 0xa6, 0xa9, 0xfd, 0x53,
-	0x0b, 0x2a, 0x5b, 0x94, 0xc5, 0xbe, 0x9b, 0x48, 0x37, 0xc5, 0x48, 0x30, 0x59, 0xf4, 0xde, 0xe5,
-	0x44, 0x2c, 0x79, 0x3c, 0xf2, 0xa2, 0x71, 0x1c, 0x89, 0x93, 0x8a, 0x4b, 0xa5, 0x63, 0xda, 0x10,
-	0x54, 0xac, 0xb8, 0x68, 0x07, 0x4a, 0x31, 0xb7, 0x80, 0xe2, 0x54, 0x19, 0x74, 0xea, 0xbe, 0x31,
-	0xb7, 0x18, 0x81, 0x24, 0xb3, 0x49, 0x16, 0xfb, 0x34, 0x11, 0xae, 0xbb, 0x64, 0x66, 0x93, 0x82,
-	0x8c, 0x35, 0xdf, 0xfe, 0xac, 0x00, 0x55, 0x9d, 0xc8, 0xa2, 0x3f, 0x82, 0xea, 0x50, 0xad, 0x86,
-	0xda, 0x40, 0x6f, 0x5c, 0xac, 0x7c, 0x22, 0xb3, 0x0d, 0xbe, 0x92, 0x59, 0x3c, 0x97, 0xd1, 0x70,
-	0x8a, 0x8a, 0x5c, 0x28, 0x25, 0x23, 0xea, 0xce, 0x54, 0xc7, 0xd0, 0xdd, 0x75, 0x46, 0xd4, 0xcd,
-	0x86, 0x2f, 0x0a, 0x02, 0x02, 0x1c, 0x1d, 0xc0, 0x5c, 0x22, 0x33, 0x41, 0x39, 0xa5, 0x9d, 0xd9,
-	0xd4, 0xc8, 0x6c, 0x30, 0x2b, 0xec, 0xcb, 0x4c, 0x50, 0xa9, 0xb0, 0xbf, 0xb0, 0x20, 0xad, 0x04,
-	0x74, 0xfd, 0x84, 0xa1, 0x4f, 0xce, 0x4c, 0xe2, 0x05, 0x6b, 0x50, 0xbc, 0xb5, 0x98, 0xc2, 0xb4,
-	0x60, 0xa7, 0x29, 0xc6, 0x04, 0xee, 0x43, 0xd9, 0x67, 0x74, 0xa8, 0xb7, 0xdc, 0x7b, 0x33, 0x0d,
-	0xcd, 0x48, 0xe9, 0x38, 0x26, 0x96, 0xd0, 0xf6, 0x7f, 0x19, 0x43, 0xe2, 0xd3, 0xca, 0x95, 0xea,
-	0x3b, 0x9e, 0xe9, 0x95, 0x8a, 0x2c, 0x9a, 0x2f, 0xd9, 0xf9, 0x57, 0x44, 0x7d, 0x58, 0xf0, 0x68,
-	0x40, 0xf9, 0xbe, 0x5e, 0xa7, 0x01, 0x39, 0x9a, 0xf2, 0xb2, 0xe8, 0xea, 0xc9, 0xf1, 0xea, 0xc2,
-	0xba, 0x09, 0x84, 0xf3, 0xb8, 0xf6, 0x4f, 0x0a, 0xb0, 0x98, 0x5f, 0x5b, 0xf4, 0x36, 0x94, 0x47,
-	0x03, 0x5d, 0x6f, 0xad, 0xb5, 0x57, 0x74, 0x07, 0x77, 0x38, 0xf1, 0xf4, 0x78, 0x75, 0x41, 0xcb,
-	0x0b, 0x02, 0x96, 0xc2, 0x7c, 0x97, 0x0d, 0x69, 0x92, 0xf0, 0x14, 0x63, 0x22, 0x9e, 0xd8, 0x92,
-	0x64, 0xac, 0xf9, 0xc8, 0x05, 0x70, 0xa3, 0xd0, 0xf3, 0xa5, 0xbf, 0x2e, 0x8a, 0x59, 0x5c, 0xbb,
-	0xd8, 0xc8, 0x3a, 0xba, 0x5d, 0xb6, 0xb3, 0x52, 0x52, 0x82, 0x0d, 0x58, 0x44, 0xa0, 0x1e, 0x90,
-	0x84, 0xc9, 0xda, 0x89, 0xa7, 0x82, 0xb6, 0xdf, 0xb9, 0x98, 0x96, 0x5d, 0x7f, 0x48, 0x33, 0x8f,
-	0xdf, 0xcd, 0x60, 0xb0, 0x89, 0x69, 0xff, 0xac, 0x00, 0x05, 0xe7, 0xc6, 0x05, 0x02, 0x48, 0x9e,
-	0x75, 0x8e, 0xdd, 0x03, 0x7a, 0xe6, 0xde, 0xa3, 0x2d, 0xa8, 0x58, 0x71, 0xb9, 0x5c, 0x4c, 0xfb,
-	0x3c, 0x24, 0x9b, 0xb8, 0x3e, 0xc3, 0x82, 0x8a, 0x15, 0x17, 0x1d, 0x42, 0xdd, 0xcd, 0xae, 0x81,
-	0xd5, 0xd8, 0xa6, 0xdb, 0xd7, 0xf9, 0x1b, 0xe5, 0xf6, 0x15, 0x51, 0x27, 0xcc, 0x08, 0xd8, 0x54,
-	0x84, 0x1e, 0x43, 0x95, 0xaa, 0x4b, 0x5a, 0x55, 0x50, 0xfe, 0x60, 0x5a, 0xa5, 0xfa, 0xb2, 0x57,
-	0x9e, 0xf1, 0xfa, 0x0b, 0xa7, 0xf8, 0xf6, 0x0f, 0x60, 0xce, 0xb9, 0x21, 0x62, 0x2b, 0x07, 0x0a,
-	0xc9, 0x0d, 0x35, 0xc8, 0xdf, 0x9d, 0x6e, 0xb3, 0xdd, 0x68, 0x83, 0x9a, 0xca, 0x82, 0x73, 0x03,
-	0x17, 0x92, 0x1b, 0xf6, 0x7f, 0x58, 0x50, 0x75, 0x6e, 0xa8, 0x38, 0x49, 0x6a, 0xa8, 0x7c, 0xad,
-	0x1a, 0xd0, 0x3e, 0xc0, 0x28, 0x0a, 0x82, 0x1d, 0x1a, 0xfb, 0x91, 0x27, 0x6a, 0x85, 0x97, 0xdf,
-	0xbf, 0xa9, 0x91, 0xef, 0xa4, 0x48, 0xd8, 0x40, 0xb5, 0xff, 0xc7, 0x02, 0x11, 0x93, 0xa2, 0x0f,
-	0xa0, 0x36, 0xa4, 0xee, 0x80, 0x84, 0x7e, 0x32, 0x54, 0x86, 0xa8, 0xc3, 0xb0, 0xda, 0x96, 0x66,
-	0xf0, 0xbd, 0xcb, 0xa5, 0x53, 0x02, 0xce, 0x1a, 0xa1, 0x4d, 0x28, 0x8d, 0x13, 0x1a, 0x5f, 0xee,
-	0x8a, 0x5f, 0xd4, 0xcd, 0xf7, 0x12, 0x1a, 0xab, 0xaa, 0x8c, 0x80, 0x40, 0x7b, 0x50, 0xd5, 0xa5,
-	0x20, 0x75, 0xe6, 0xcc, 0x50, 0x55, 0x4a, 0xa1, 0xec, 0xff, 0x2d, 0x40, 0x2d, 0xbd, 0x3f, 0x42,
-	0x63, 0xa8, 0xf1, 0x33, 0x47, 0xdc, 0x56, 0xaa, 0x93, 0xa5, 0x35, 0xed, 0x95, 0x94, 0xa3, 0x81,
-	0x8c, 0x04, 0xdd, 0xa0, 0xe2, 0x4c, 0x13, 0xfa, 0x13, 0x0b, 0x96, 0xa2, 0x10, 0x53, 0x37, 0x8a,
-	0xbd, 0xed, 0x88, 0xdd, 0x8e, 0xc6, 0xa1, 0x37, 0xd3, 0xf9, 0x9d, 0x57, 0x7f, 0x72, 0xbc, 0xba,
-	0x74, 0x6f, 0x02, 0x1e, 0x9f, 0x51, 0x88, 0x06, 0x50, 0x89, 0x42, 0x11, 0x38, 0xa9, 0x09, 0xfe,
-	0x1a, 0x74, 0x8b, 0x34, 0xf1, 0x9e, 0x44, 0xc5, 0x1a, 0xde, 0xbe, 0x0b, 0xb9, 0xa9, 0x40, 0xaf,
-	0x40, 0x31, 0x79, 0x72, 0xa6, 0x20, 0xe1, 0xdc, 0xef, 0x62, 0x4e, 0x4f, 0xef, 0xb2, 0x0b, 0xe7,
-	0xdd, 0x65, 0xdb, 0x3f, 0x2b, 0x42, 0xc9, 0xd9, 0x6d, 0x6d, 0x5f, 0xc0, 0x65, 0x7e, 0x07, 0x2a,
-	0x21, 0x61, 0xc9, 0x5e, 0x1c, 0xa8, 0x4a, 0x5d, 0x7a, 0x9c, 0x6c, 0xb7, 0x76, 0x9d, 0x3d, 0xdc,
-	0xc5, 0x9a, 0x8f, 0xee, 0xc0, 0x55, 0xfe, 0x73, 0x2b, 0x0a, 0x7d, 0x16, 0xc5, 0x7e, 0xd8, 0xe7,
-	0x8d, 0xaa, 0xa2, 0xd1, 0x37, 0x55, 0xa3, 0xab, 0xbc, 0x91, 0x21, 0x80, 0xbb, 0xf8, 0x6c, 0x1b,
-	0xb4, 0x06, 0x35, 0x75, 0x2b, 0xb2, 0xe9, 0xa9, 0x2b, 0x81, 0xf4, 0x9e, 0x42, 0xdd, 0x9d, 0x6c,
-	0xae, 0xe3, 0x4c, 0x86, 0x77, 0x32, 0x19, 0x8b, 0xc0, 0x4e, 0x39, 0xec, 0xac, 0x6a, 0x2d, 0xc9,
-	0x58, 0xf3, 0x51, 0x17, 0x16, 0xd4, 0xcf, 0x9d, 0x98, 0xf6, 0xfc, 0xa7, 0xea, 0xf2, 0xe0, 0xdb,
-	0xaa, 0xc1, 0x82, 0x63, 0x32, 0x4f, 0x27, 0x09, 0x38, 0xdf, 0x18, 0x7d, 0x0c, 0x25, 0x32, 0x66,
-	0x03, 0xe5, 0xb2, 0xa6, 0x8c, 0x40, 0x76, 0x5b, 0xdb, 0xad, 0x31, 0x1b, 0xa8, 0x55, 0x1a, 0xb3,
-	0x01, 0x16, 0xa0, 0xe8, 0x1d, 0xa8, 0x0f, 0xc9, 0xd3, 0xcd, 0xb0, 0x17, 0xf8, 0xfd, 0x81, 0xac,
-	0xd7, 0x2e, 0x64, 0xa7, 0xe1, 0x56, 0xc6, 0xc2, 0xa6, 0x9c, 0x8d, 0xa1, 0xaa, 0x21, 0xd1, 0x6d,
-	0x9e, 0x11, 0x1c, 0xd0, 0xf0, 0x72, 0xd5, 0xb1, 0x9a, 0x4c, 0x1a, 0x0e, 0x68, 0x88, 0x65, 0x73,
-	0xfb, 0x9f, 0x2c, 0x28, 0x3b, 0x2e, 0x09, 0x44, 0xbd, 0x69, 0xe8, 0x87, 0xea, 0xfa, 0x47, 0x16,
-	0x09, 0xca, 0x46, 0xa7, 0x32, 0x16, 0x36, 0xe5, 0xd0, 0x9b, 0x62, 0x2c, 0x69, 0xb3, 0x82, 0x18,
-	0xcb, 0x15, 0x35, 0x0e, 0xa3, 0x49, 0xf6, 0x81, 0x6e, 0xc2, 0xbc, 0xba, 0x5c, 0xc2, 0xdc, 0x09,
-	0xab, 0xa7, 0x34, 0xa9, 0x63, 0xc0, 0x06, 0x0f, 0xe7, 0x24, 0x6d, 0x0f, 0xf4, 0x6d, 0x45, 0xfe,
-	0xe9, 0x85, 0xf5, 0xb5, 0x3e, 0xbd, 0xf8, 0xac, 0x04, 0x25, 0x71, 0x2e, 0xfe, 0xea, 0x4d, 0xf4,
-	0x10, 0x4a, 0x09, 0x23, 0xe1, 0x6c, 0xc5, 0x8f, 0xdd, 0xd6, 0xb6, 0x2a, 0x7e, 0xec, 0xb6, 0xb6,
-	0xb1, 0x00, 0xcc, 0x0a, 0x0b, 0xb3, 0x3c, 0x9a, 0x49, 0xab, 0x27, 0x72, 0xe1, 0x73, 0x85, 0x05,
-	0x07, 0x8a, 0x41, 0xa4, 0x4b, 0x6d, 0xd3, 0xd5, 0x82, 0xba, 0x51, 0x5f, 0xd6, 0x82, 0xba, 0x51,
-	0x1f, 0x73, 0x34, 0xbe, 0x6b, 0x44, 0x31, 0xb1, 0x3c, 0xc3, 0xae, 0xd1, 0x95, 0xd9, 0xc9, 0x82,
-	0xa2, 0x8a, 0x21, 0xe4, 0x31, 0xff, 0xee, 0x94, 0x31, 0x84, 0x00, 0x9e, 0x33, 0x62, 0x08, 0x07,
-	0x0a, 0xde, 0xbe, 0xda, 0xe5, 0xef, 0x4e, 0x79, 0xcd, 0x9d, 0x81, 0xae, 0xb7, 0x71, 0xc1, 0xdb,
-	0xb7, 0xff, 0xa5, 0x0c, 0xea, 0x3d, 0xd6, 0xc5, 0x4c, 0xc8, 0x8d, 0xa3, 0xd9, 0x4c, 0xa8, 0x13,
-	0x47, 0xa1, 0x9c, 0x2f, 0xfe, 0x0b, 0x0b, 0xc0, 0xd4, 0x36, 0x8b, 0x5f, 0xb7, 0x6d, 0x12, 0x6d,
-	0x9b, 0x33, 0xd7, 0x69, 0xd5, 0xfd, 0xc0, 0x59, 0xeb, 0xfc, 0x41, 0xce, 0x90, 0xa6, 0xaf, 0xb9,
-	0x2b, 0x05, 0x93, 0xa6, 0xb4, 0x27, 0x4c, 0xa9, 0x3a, 0x8b, 0x6f, 0x57, 0x91, 0x6d, 0xce, 0x98,
-	0xf6, 0x84, 0x31, 0xcd, 0xcd, 0xf2, 0x88, 0xa6, 0x6d, 0xc2, 0x4a, 0x73, 0xe2, 0xf3, 0x1d, 0x53,
-	0x16, 0x1f, 0x29, 0x33, 0x9d, 0xee, 0x66, 0x49, 0xbd, 0xe7, 0xcc, 0xb2, 0x61, 0xcc, 0x21, 0xb1,
-	0x44, 0xb6, 0xff, 0xb1, 0x00, 0xf3, 0x52, 0xb3, 0x4a, 0x51, 0x5f, 0x85, 0xca, 0x88, 0x86, 0x9e,
-	0x1f, 0xf6, 0x85, 0xfd, 0x94, 0x64, 0xf0, 0xb2, 0x23, 0x49, 0x58, 0xf3, 0xd0, 0x11, 0xcf, 0x49,
-	0x45, 0x8d, 0xaa, 0x51, 0x9a, 0xa1, 0x2a, 0x68, 0xaa, 0x6e, 0xaa, 0xa2, 0x97, 0x2c, 0xcc, 0x19,
-	0x39, 0xae, 0xa0, 0x62, 0xad, 0x6f, 0xf9, 0x29, 0xcc, 0x9b, 0x92, 0xe7, 0xd4, 0xd6, 0xb0, 0x59,
-	0x5b, 0x9b, 0x76, 0xde, 0xb4, 0x5e, 0xa3, 0x32, 0xf7, 0xaf, 0x05, 0x28, 0x39, 0x8c, 0x8e, 0x9e,
-	0x43, 0xfd, 0xea, 0x51, 0xae, 0x7e, 0x35, 0x63, 0x21, 0xe4, 0xbc, 0xda, 0x55, 0x7f, 0xa2, 0x76,
-	0x35, 0xf3, 0x2b, 0x86, 0x67, 0xd5, 0xad, 0x3e, 0xe7, 0xe9, 0x20, 0xa3, 0xa3, 0xe7, 0x50, 0xb3,
-	0xfa, 0xc3, 0x7c, 0xcd, 0xea, 0xd6, 0xd4, 0x43, 0x7a, 0x46, 0xbd, 0xea, 0xef, 0xae, 0xca, 0xa1,
-	0x88, 0x5a, 0x95, 0x76, 0xf0, 0x73, 0xcf, 0x74, 0xf0, 0x0e, 0x14, 0x5d, 0xc2, 0x1a, 0x57, 0x66,
-	0x38, 0x69, 0x3b, 0x84, 0xc9, 0x93, 0xb6, 0x43, 0x18, 0xe6, 0x68, 0xe8, 0x00, 0x6a, 0xae, 0x7e,
-	0xde, 0xab, 0xa6, 0x70, 0xba, 0x18, 0x21, 0x7d, 0x24, 0x2c, 0x6f, 0x69, 0xd3, 0x4f, 0x9c, 0xe1,
-	0xa3, 0x47, 0x30, 0xe7, 0x89, 0xf7, 0x59, 0x8d, 0xdf, 0x9c, 0xe5, 0xa0, 0x14, 0x10, 0x6d, 0x10,
-	0x8f, 0xce, 0xc4, 0x6f, 0xac, 0x60, 0xb9, 0x02, 0x2a, 0x1e, 0x5f, 0x35, 0x96, 0x67, 0x50, 0x20,
-	0xdf, 0x6f, 0x49, 0x05, 0xf2, 0x37, 0x56, 0xb0, 0xe8, 0x0d, 0x98, 0xeb, 0xf9, 0x01, 0xa3, 0xb1,
-	0x4a, 0x5b, 0x1a, 0xe9, 0xad, 0xbe, 0xa0, 0x9e, 0xa6, 0xbf, 0xb0, 0x92, 0x43, 0x2e, 0x54, 0x7a,
-	0xf2, 0x15, 0x58, 0xe3, 0x9b, 0x33, 0xb8, 0x0f, 0xf5, 0x92, 0x4c, 0xba, 0x4f, 0xf5, 0x81, 0x35,
-	0x32, 0x37, 0x8d, 0xbe, 0xcf, 0xc4, 0xa3, 0xb0, 0x69, 0x4d, 0xe3, 0x8e, 0xaf, 0x4c, 0xe3, 0x8e,
-	0xcf, 0x30, 0x47, 0x43, 0x1f, 0x43, 0xb9, 0x2f, 0x1e, 0x3c, 0xd4, 0x67, 0xb8, 0x93, 0x12, 0x6f,
-	0x1c, 0xe4, 0xc1, 0x2c, 0xdf, 0x48, 0x48, 0x4c, 0x11, 0xad, 0x44, 0x1e, 0x55, 0x47, 0xd1, 0x94,
-	0xd1, 0x4a, 0xe4, 0xa9, 0x23, 0x99, 0xff, 0xc2, 0x02, 0x10, 0xfd, 0x16, 0x14, 0x87, 0x64, 0xa4,
-	0x1e, 0xd4, 0x69, 0xa7, 0x58, 0xdc, 0x22, 0xa3, 0x53, 0xf9, 0x07, 0x73, 0x36, 0x7a, 0x0d, 0xaa,
-	0xb1, 0x4e, 0x35, 0xbe, 0x21, 0xd2, 0x86, 0xd4, 0x11, 0xa4, 0xb9, 0x46, 0x2a, 0xc1, 0x67, 0x22,
-	0xe1, 0xb9, 0x4d, 0xa3, 0x31, 0xc3, 0x4c, 0x88, 0xec, 0x48, 0xce, 0x84, 0xf8, 0x89, 0x25, 0x26,
-	0xea, 0x41, 0x45, 0xa7, 0x1f, 0xb2, 0xc0, 0xfa, 0xee, 0x0c, 0x47, 0x9f, 0x91, 0xd7, 0xaa, 0x7c,
-	0x44, 0x83, 0x73, 0x6f, 0x96, 0xf8, 0xe1, 0x81, 0x3e, 0x60, 0xa7, 0xf4, 0x66, 0x3c, 0x44, 0xcd,
-	0x0a, 0xe1, 0x1c, 0x0f, 0x4b, 0x58, 0xf4, 0x08, 0x16, 0x62, 0x2a, 0x2e, 0x0b, 0xd5, 0xa3, 0x3b,
-	0x99, 0x97, 0xdf, 0xd2, 0x79, 0x33, 0x36, 0x99, 0xa7, 0xc7, 0xab, 0xd7, 0xce, 0x79, 0x77, 0x97,
-	0x93, 0xc1, 0x79, 0x3c, 0xf4, 0x16, 0x00, 0xa3, 0xf1, 0xd0, 0x0f, 0x09, 0x8b, 0xe4, 0xd3, 0x35,
-	0xe3, 0xe9, 0xea, 0x6e, 0xca, 0xc1, 0x86, 0x14, 0xda, 0x80, 0x8a, 0xfc, 0x07, 0x82, 0xa4, 0xb1,
-	0xf0, 0xec, 0x17, 0x42, 0xf2, 0x3f, 0x0e, 0x8c, 0x7b, 0x75, 0xd9, 0x04, 0xeb, 0xb6, 0xe8, 0xfb,
-	0x80, 0xd4, 0xdb, 0x88, 0x96, 0xeb, 0x46, 0xe3, 0x90, 0x89, 0xa7, 0x14, 0x8b, 0xb9, 0x7f, 0xb7,
-	0x40, 0xce, 0x19, 0x09, 0x7c, 0x4e, 0x2b, 0xd4, 0x37, 0xce, 0xac, 0xa5, 0x19, 0x8e, 0x63, 0x7d,
-	0xff, 0x28, 0xeb, 0xb2, 0xfa, 0xcb, 0x38, 0xbe, 0xfe, 0xc2, 0x82, 0xf9, 0x30, 0xf2, 0xa8, 0xce,
-	0xda, 0x1b, 0x57, 0xc5, 0x0c, 0xdc, 0x9b, 0xe9, 0xf0, 0x6f, 0x6e, 0x1b, 0x88, 0x32, 0xb4, 0x4a,
-	0x13, 0x6e, 0x93, 0x85, 0x73, 0xaa, 0xd1, 0x6d, 0xa8, 0x92, 0x5e, 0xcf, 0x0f, 0x7d, 0x76, 0xd4,
-	0x40, 0x62, 0xd0, 0x2f, 0x9f, 0xb7, 0x10, 0x2d, 0x25, 0x23, 0xc7, 0xa4, 0xbf, 0x70, 0xda, 0x16,
-	0xed, 0x41, 0x9d, 0x45, 0x01, 0x8d, 0xd5, 0x0d, 0xf2, 0x8b, 0x62, 0x44, 0x2b, 0xe7, 0x41, 0xed,
-	0xa6, 0x62, 0x59, 0xf1, 0x21, 0xa3, 0x25, 0xd8, 0xc4, 0x31, 0x9f, 0x44, 0xbe, 0xfc, 0xdc, 0x9f,
-	0x44, 0xbe, 0xf4, 0xeb, 0x7b, 0x12, 0xb9, 0xfc, 0x3e, 0x5c, 0x3d, 0xb3, 0x60, 0x97, 0xba, 0x3d,
-	0xfe, 0xfb, 0x0a, 0x18, 0xef, 0x48, 0xd1, 0x1b, 0xf9, 0x1b, 0xa7, 0xe5, 0xc9, 0x1b, 0xa7, 0x1a,
-	0x97, 0xcd, 0xdd, 0x36, 0x89, 0x9b, 0x12, 0x92, 0x44, 0xa1, 0x3a, 0x31, 0x8d, 0x9b, 0x12, 0x4e,
-	0xc5, 0x8a, 0x7b, 0x99, 0x5b, 0x29, 0xd3, 0x79, 0x97, 0x7f, 0xa5, 0xf3, 0x7e, 0x0d, 0xaa, 0x89,
-	0xde, 0x01, 0x95, 0x89, 0x7f, 0x7c, 0xd1, 0xc6, 0x9a, 0x4a, 0x20, 0x0f, 0xe6, 0x03, 0x92, 0x30,
-	0xe1, 0xa1, 0xbd, 0x16, 0x53, 0x49, 0xd8, 0x65, 0x6e, 0xa3, 0xd2, 0xed, 0xd0, 0x35, 0x70, 0x70,
-	0x0e, 0x15, 0xfd, 0xd8, 0x82, 0xc5, 0xc4, 0xc8, 0x55, 0x52, 0xdf, 0xef, 0xcc, 0x18, 0x36, 0xe7,
-	0x32, 0x20, 0xaa, 0x72, 0x9f, 0xeb, 0xfa, 0x79, 0x72, 0x9e, 0x79, 0x7a, 0x86, 0x82, 0x27, 0x3a,
-	0x85, 0xfe, 0xd6, 0x82, 0x79, 0xee, 0xdd, 0xd3, 0x5e, 0xca, 0xb3, 0xe3, 0xfe, 0xcc, 0xbd, 0x34,
-	0x30, 0x65, 0x1f, 0x5f, 0x4d, 0x9f, 0xa2, 0x68, 0xd6, 0xb9, 0x1d, 0xcc, 0xf5, 0x66, 0xf9, 0x4f,
-	0x2d, 0x78, 0xf1, 0x9c, 0x01, 0x9f, 0x63, 0xe0, 0x0f, 0xf3, 0x29, 0x5c, 0x6b, 0xe6, 0xec, 0xd2,
-	0x7c, 0x9c, 0xf1, 0x23, 0x0b, 0xae, 0x9e, 0x19, 0xd1, 0x73, 0xee, 0x84, 0xfd, 0x00, 0xf4, 0x3b,
-	0xcf, 0x8b, 0xd5, 0xec, 0x93, 0xf1, 0xfe, 0x0e, 0x61, 0x83, 0xc9, 0xcd, 0xe6, 0x48, 0x32, 0xd6,
-	0x7c, 0xfb, 0x2f, 0x0b, 0x50, 0xdc, 0xed, 0x3a, 0xe8, 0x63, 0x98, 0x77, 0x49, 0x87, 0xc6, 0x4c,
-	0x3d, 0x0e, 0xbe, 0xfc, 0xff, 0x4a, 0x75, 0x5a, 0x59, 0x73, 0x9c, 0x03, 0x43, 0x7b, 0x00, 0x6e,
-	0x06, 0x7d, 0xf9, 0x8b, 0x2d, 0x03, 0xd8, 0x00, 0x42, 0x18, 0x6a, 0x07, 0xe9, 0x6b, 0xe6, 0x4b,
-	0xdd, 0x6f, 0x89, 0x1c, 0x26, 0x7b, 0xc3, 0x9c, 0xc1, 0xb4, 0x9b, 0x9f, 0x7f, 0xb5, 0xf2, 0xc2,
-	0x17, 0x5f, 0xad, 0xbc, 0xf0, 0xe5, 0x57, 0x2b, 0x2f, 0xfc, 0xf0, 0x64, 0xc5, 0xfa, 0xfc, 0x64,
-	0xc5, 0xfa, 0xe2, 0x64, 0xc5, 0xfa, 0xf2, 0x64, 0xc5, 0xfa, 0xf9, 0xc9, 0x8a, 0xf5, 0x57, 0xbf,
-	0x58, 0x79, 0xe1, 0x0f, 0xaa, 0x7a, 0xbd, 0xfe, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x65, 0x95, 0x0e,
-	0x20, 0x46, 0x3d, 0x00, 0x00,
+	// 4248 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x4d, 0x70, 0x1b, 0x47,
+	0x76, 0xd6, 0x00, 0x20, 0x01, 0x3c, 0x90, 0x14, 0xd5, 0x72, 0x65, 0xb1, 0x8c, 0x4d, 0xaa, 0x66,
+	0xe3, 0x8d, 0x36, 0x65, 0x83, 0xb6, 0x64, 0x57, 0xa4, 0x75, 0xbc, 0x36, 0x00, 0x52, 0x32, 0x57,
+	0x20, 0x45, 0xf5, 0x90, 0x52, 0x1c, 0x7b, 0xa3, 0x34, 0x67, 0x1a, 0xc0, 0x88, 0x83, 0x19, 0x68,
+	0xa6, 0x41, 0x8b, 0x39, 0x6d, 0x6d, 0x7e, 0xaa, 0x72, 0x48, 0x55, 0x72, 0xc8, 0x2d, 0x57, 0x27,
+	0xa7, 0x54, 0xaa, 0x52, 0x49, 0x55, 0xf6, 0xe2, 0x4b, 0x0e, 0xf1, 0xd1, 0x55, 0x7b, 0x71, 0x6d,
+	0x2a, 0xac, 0x35, 0x37, 0xa7, 0x1c, 0x73, 0xc8, 0x81, 0xa7, 0xad, 0xfe, 0x9b, 0xe9, 0x01, 0xa9,
+	0x5d, 0x12, 0xb0, 0x75, 0x22, 0xe6, 0xbd, 0xd7, 0xdf, 0xeb, 0x9f, 0xd7, 0xaf, 0xdf, 0x7b, 0xdd,
+	0x84, 0x76, 0xcf, 0x67, 0xfd, 0xd1, 0x5e, 0xc3, 0x8d, 0x06, 0xab, 0x24, 0xee, 0x45, 0xc3, 0x38,
+	0x7a, 0xf2, 0x7a, 0x40, 0xf6, 0x12, 0xf1, 0xf5, 0xba, 0x47, 0x18, 0xe9, 0x06, 0xd1, 0x27, 0xab,
+	0x64, 0xe8, 0xaf, 0x1e, 0xbc, 0x49, 0x82, 0x61, 0x9f, 0xbc, 0xb9, 0xda, 0xa3, 0x21, 0x8d, 0x09,
+	0xa3, 0x5e, 0x63, 0x18, 0x47, 0x2c, 0x42, 0x37, 0x33, 0x90, 0x86, 0x06, 0x79, 0xcc, 0x41, 0xc4,
+	0xd7, 0x63, 0x0d, 0xd2, 0x20, 0x43, 0xbf, 0xa1, 0x41, 0x96, 0x5e, 0x37, 0x34, 0xf7, 0xa2, 0x5e,
+	0xb4, 0x2a, 0xb0, 0xf6, 0x46, 0x5d, 0xf1, 0x25, 0x3e, 0xc4, 0x2f, 0xa9, 0x63, 0xc9, 0xde, 0xbf,
+	0x95, 0x34, 0xfc, 0x48, 0x74, 0xc4, 0x8d, 0x62, 0xba, 0x7a, 0x70, 0xaa, 0x1f, 0x4b, 0x6f, 0x65,
+	0x32, 0x03, 0xe2, 0xf6, 0xfd, 0x90, 0xc6, 0x87, 0xab, 0xc3, 0xfd, 0x9e, 0x68, 0x14, 0xd3, 0x24,
+	0x1a, 0xc5, 0x2e, 0xbd, 0x50, 0xab, 0x64, 0x75, 0x40, 0x19, 0x39, 0x43, 0x97, 0xfd, 0xa5, 0x05,
+	0x0b, 0xcd, 0x47, 0x4e, 0x3b, 0xa6, 0x1e, 0x0d, 0x99, 0x4f, 0x82, 0x04, 0x7d, 0x0c, 0x35, 0xe2,
+	0xba, 0x34, 0x49, 0xee, 0xd1, 0xc3, 0x0d, 0xaf, 0x6e, 0x5d, 0xb3, 0xae, 0xd7, 0x6e, 0xbc, 0xda,
+	0x90, 0xf0, 0x62, 0xf0, 0xbc, 0xe3, 0x8d, 0x83, 0x37, 0x1b, 0x0e, 0x75, 0x63, 0xca, 0xee, 0xd1,
+	0x43, 0x87, 0x06, 0xd4, 0x65, 0x51, 0xdc, 0xba, 0xfa, 0xf9, 0xd1, 0xca, 0xa5, 0xe3, 0xa3, 0x95,
+	0x5a, 0x33, 0x45, 0x58, 0xc3, 0x26, 0x1c, 0xea, 0xc3, 0xe5, 0x44, 0x34, 0x4b, 0x25, 0xea, 0x85,
+	0x8b, 0x68, 0xf8, 0x96, 0xd2, 0x70, 0xd9, 0xc9, 0xa3, 0xe0, 0x71, 0x58, 0xfb, 0x35, 0xa8, 0x35,
+	0x1f, 0x39, 0xeb, 0xa1, 0x37, 0x8c, 0xfc, 0x90, 0xa1, 0x57, 0xa0, 0x38, 0x8a, 0x03, 0x31, 0x9c,
+	0x6a, 0xab, 0xa6, 0x50, 0x8a, 0xbb, 0xb8, 0x83, 0x39, 0xdd, 0xfe, 0x59, 0x01, 0xca, 0x2d, 0xe2,
+	0xee, 0x47, 0xdd, 0x2e, 0xfa, 0x18, 0x2a, 0xde, 0x28, 0x26, 0xcc, 0x8f, 0xc2, 0x7a, 0x49, 0x74,
+	0xae, 0x61, 0x74, 0x2e, 0x9d, 0xdd, 0xc6, 0x70, 0xbf, 0xc7, 0x09, 0x49, 0x83, 0xcf, 0x2e, 0xef,
+	0xee, 0x9a, 0x6a, 0xd5, 0x5a, 0x54, 0xf8, 0x15, 0x4d, 0xc1, 0x29, 0x22, 0x7a, 0x03, 0x16, 0xef,
+	0x10, 0x3e, 0x96, 0x6d, 0x1a, 0xbb, 0x34, 0x64, 0xa4, 0x47, 0xeb, 0x33, 0xd7, 0xac, 0xeb, 0xf3,
+	0xad, 0x12, 0x6f, 0x85, 0x4f, 0x71, 0xd1, 0x77, 0x60, 0x26, 0x61, 0x74, 0x98, 0x88, 0xce, 0x97,
+	0x5a, 0xf3, 0x0a, 0x7c, 0xc6, 0xe1, 0x44, 0x2c, 0x79, 0x68, 0x13, 0x8a, 0x2e, 0x19, 0xaa, 0xc9,
+	0xbc, 0x68, 0x7f, 0xd3, 0xf9, 0x68, 0x93, 0x21, 0xe6, 0x38, 0x68, 0x0d, 0x16, 0x9f, 0xf8, 0x8c,
+	0x51, 0xb3, 0x97, 0x45, 0xd1, 0xcb, 0xba, 0x92, 0x5d, 0xfc, 0xe1, 0x18, 0x1f, 0x9f, 0x6a, 0x61,
+	0xcf, 0x40, 0xb1, 0x4d, 0x98, 0xed, 0x41, 0xa9, 0x1d, 0x79, 0x14, 0xbd, 0x05, 0xe5, 0x78, 0x14,
+	0x32, 0x7f, 0x40, 0xc5, 0xbc, 0x56, 0x5b, 0x4b, 0x0a, 0xab, 0x8c, 0x25, 0xf9, 0x24, 0xfb, 0x89,
+	0xb5, 0x28, 0xfa, 0x2e, 0xcc, 0x4a, 0x9b, 0x17, 0x1d, 0xa8, 0xb6, 0x16, 0x54, 0xa3, 0x59, 0x47,
+	0x50, 0xb1, 0xe2, 0xda, 0x9f, 0x15, 0xa1, 0xda, 0x8e, 0x42, 0x46, 0xf8, 0x68, 0xf9, 0xa4, 0xf9,
+	0x03, 0xde, 0x6b, 0xb9, 0xe2, 0xe9, 0xa4, 0x6d, 0x70, 0x22, 0x96, 0x3c, 0xf4, 0x21, 0xcc, 0x1d,
+	0x44, 0xc1, 0x68, 0x40, 0x37, 0xa3, 0x51, 0xc8, 0x92, 0xfa, 0xcc, 0xb5, 0xe2, 0xf5, 0xda, 0x8d,
+	0x95, 0xb3, 0x4c, 0xf1, 0x61, 0x26, 0xd7, 0x7a, 0x49, 0x81, 0xcd, 0x19, 0xc4, 0x04, 0xe7, 0xa0,
+	0xd0, 0x43, 0x28, 0xf8, 0xa1, 0xe8, 0x71, 0xed, 0xc6, 0x0f, 0x1a, 0x13, 0xb8, 0x96, 0xc6, 0x46,
+	0xc8, 0x68, 0xdc, 0x25, 0x2e, 0x6d, 0xcd, 0x1e, 0x1f, 0xad, 0x14, 0x36, 0x42, 0x5c, 0xf0, 0x43,
+	0xf4, 0x2a, 0x94, 0xdd, 0x68, 0x30, 0x20, 0xa1, 0x57, 0x9f, 0xbd, 0x56, 0xe4, 0xb6, 0xcc, 0xe7,
+	0xaf, 0x2d, 0x49, 0x58, 0xf3, 0xd0, 0xcb, 0x50, 0x22, 0x71, 0x2f, 0xa9, 0x97, 0x85, 0x4c, 0xe5,
+	0xf8, 0x68, 0xa5, 0xd4, 0x8c, 0x7b, 0x09, 0x16, 0x54, 0x74, 0x1b, 0x8a, 0x34, 0x3c, 0xa8, 0x57,
+	0xc4, 0x70, 0x97, 0xce, 0x1a, 0xee, 0x7a, 0x78, 0xf0, 0x90, 0xc4, 0x99, 0x61, 0xac, 0x87, 0x07,
+	0x98, 0xb7, 0x41, 0x1f, 0x42, 0x55, 0xfb, 0xa0, 0xa4, 0x5e, 0x15, 0xc3, 0xbb, 0x7e, 0x16, 0x00,
+	0x56, 0x42, 0x98, 0x3e, 0x1d, 0xf9, 0x31, 0x1d, 0xd0, 0x90, 0x25, 0xad, 0x2b, 0x0a, 0xae, 0xaa,
+	0xb9, 0x09, 0xce, 0xd0, 0xec, 0x8f, 0xa1, 0xd4, 0x8e, 0xa3, 0x10, 0xbd, 0x06, 0x95, 0xc4, 0xed,
+	0x53, 0x6f, 0x14, 0xe8, 0xd5, 0x4b, 0xf7, 0x93, 0xa3, 0xe8, 0x38, 0x95, 0xe0, 0xe6, 0x11, 0x90,
+	0xc3, 0x68, 0xc4, 0x84, 0xed, 0x1b, 0xe6, 0xd1, 0x11, 0x54, 0xac, 0xb8, 0xf6, 0x3f, 0x5a, 0x30,
+	0xb7, 0xd6, 0x5a, 0x23, 0x8c, 0x48, 0xbb, 0xe1, 0x16, 0x72, 0x40, 0x82, 0xd1, 0x29, 0x0b, 0x79,
+	0xc8, 0x89, 0x58, 0xf2, 0x50, 0x0c, 0x55, 0xf1, 0xe3, 0x4e, 0x1c, 0x0d, 0xd4, 0xe6, 0x5a, 0x9f,
+	0x68, 0x35, 0x4d, 0xd5, 0x1c, 0xac, 0x35, 0xcf, 0xe7, 0xe1, 0xa1, 0xc6, 0xc6, 0x99, 0x1a, 0x3b,
+	0x82, 0xc5, 0x71, 0x69, 0xf4, 0x11, 0xcc, 0x25, 0xda, 0x19, 0x62, 0xda, 0xbd, 0x98, 0x5b, 0x5e,
+	0xe4, 0xb6, 0xea, 0x18, 0xcd, 0x71, 0x0e, 0xcc, 0xfe, 0x85, 0x05, 0xb3, 0x6b, 0x2d, 0xc7, 0x0f,
+	0xf7, 0xd1, 0x3e, 0x54, 0x78, 0xff, 0xf7, 0x48, 0x42, 0x95, 0x8e, 0x77, 0x27, 0x1b, 0xae, 0x02,
+	0x31, 0x5c, 0xa1, 0xa2, 0xe0, 0x54, 0x01, 0xf2, 0xa1, 0x4c, 0x5c, 0xee, 0x80, 0x92, 0x7a, 0x41,
+	0x98, 0xe2, 0x64, 0x1b, 0xc5, 0x79, 0xd0, 0x69, 0x0a, 0x98, 0xd6, 0x65, 0xed, 0x4f, 0xe4, 0x77,
+	0x82, 0x35, 0xbe, 0xfd, 0x3f, 0x45, 0xa8, 0xac, 0xb5, 0xd4, 0xca, 0xbf, 0xd0, 0x41, 0x7e, 0x07,
+	0x66, 0x9e, 0x8e, 0x68, 0x7c, 0xa8, 0xcc, 0x33, 0x35, 0xb3, 0x07, 0x9c, 0x88, 0x25, 0x0f, 0xdd,
+	0x82, 0xb9, 0xa8, 0xdb, 0x4d, 0x28, 0x6b, 0x73, 0x1f, 0x12, 0x2a, 0x4f, 0x97, 0xfa, 0x99, 0xfb,
+	0x06, 0x0f, 0xe7, 0x24, 0x51, 0x1f, 0xe6, 0x86, 0x51, 0x10, 0x08, 0x67, 0x71, 0x40, 0x82, 0x09,
+	0x0f, 0xac, 0x54, 0xd3, 0xb6, 0x81, 0x85, 0x73, 0xc8, 0x28, 0x84, 0x05, 0xee, 0x5d, 0x7c, 0x96,
+	0xea, 0x9a, 0x99, 0x48, 0xd7, 0x6f, 0x29, 0x5d, 0x0b, 0xed, 0x1c, 0x1a, 0x1e, 0x43, 0x47, 0x37,
+	0x00, 0xfc, 0xd0, 0x67, 0x7c, 0xcb, 0x0f, 0x48, 0x7d, 0xf6, 0x9a, 0x75, 0xbd, 0xd2, 0x42, 0xaa,
+	0x2d, 0x6c, 0xa4, 0x1c, 0x6c, 0x48, 0xd9, 0x9f, 0x5a, 0x90, 0xae, 0x01, 0xf7, 0x0c, 0x5e, 0xec,
+	0x1f, 0xd0, 0x58, 0xed, 0xf0, 0xd4, 0x33, 0xac, 0x09, 0x2a, 0x56, 0x5c, 0xf4, 0x14, 0xc0, 0x4b,
+	0x77, 0x9b, 0xda, 0xe4, 0xcd, 0xa9, 0x37, 0x79, 0x6b, 0x81, 0xf7, 0x33, 0xfb, 0xc6, 0x86, 0x12,
+	0xfb, 0x27, 0x7c, 0xc7, 0x51, 0x6f, 0x34, 0xa4, 0x22, 0x30, 0xf1, 0xbd, 0x53, 0x81, 0xc9, 0xc6,
+	0x1a, 0xe6, 0x74, 0xf4, 0x21, 0x94, 0x07, 0xe4, 0x99, 0xe3, 0xff, 0x29, 0x3d, 0xcf, 0xd9, 0xde,
+	0xd0, 0xde, 0xb4, 0xf1, 0x60, 0x44, 0x42, 0xe6, 0xb3, 0xc3, 0x6c, 0x4f, 0x6c, 0x4a, 0x18, 0xac,
+	0xf1, 0xec, 0x0a, 0xcc, 0xae, 0x3f, 0x1b, 0x92, 0xd0, 0xb3, 0xab, 0x50, 0xbe, 0x13, 0x10, 0xc6,
+	0x68, 0x68, 0xff, 0x72, 0x16, 0xe6, 0xef, 0x52, 0xb6, 0x1d, 0x79, 0xce, 0x90, 0xba, 0x98, 0x3e,
+	0x45, 0x6f, 0x43, 0xcd, 0x0d, 0x46, 0x09, 0xa3, 0xf1, 0x16, 0x19, 0x50, 0xe1, 0xf3, 0xab, 0x59,
+	0xa4, 0xd7, 0xce, 0x58, 0xd8, 0x94, 0xe3, 0x76, 0xef, 0xd1, 0xbd, 0x51, 0xaf, 0x3e, 0x27, 0x56,
+	0x2e, 0xb5, 0xfb, 0x35, 0x4e, 0xc4, 0x92, 0xc7, 0xed, 0x7e, 0xe8, 0x0f, 0x69, 0xe0, 0x87, 0x54,
+	0x80, 0x5b, 0x79, 0xbb, 0xdf, 0x36, 0x78, 0x38, 0x27, 0x89, 0x56, 0xa1, 0x1a, 0x92, 0x01, 0x4d,
+	0x86, 0x44, 0xad, 0x59, 0x35, 0x3b, 0x5d, 0xb6, 0x34, 0x03, 0x67, 0x32, 0xe8, 0x7b, 0x50, 0x8e,
+	0xe9, 0x30, 0xf0, 0x5d, 0x22, 0x76, 0xd7, 0x4c, 0x36, 0x31, 0x58, 0x92, 0xb1, 0xe6, 0xf3, 0x11,
+	0x8b, 0xf8, 0xe0, 0x4e, 0x14, 0x0f, 0x08, 0x53, 0xb1, 0x4a, 0x3a, 0xe2, 0x8d, 0x8c, 0x85, 0x4d,
+	0x39, 0xde, 0x2c, 0x1e, 0x85, 0x21, 0x8d, 0x85, 0x84, 0xd8, 0x1d, 0x46, 0x33, 0x9c, 0xb1, 0xb0,
+	0x29, 0x87, 0x1c, 0x80, 0xe1, 0x28, 0x08, 0xb6, 0xa3, 0xc0, 0x77, 0x0f, 0x85, 0x9d, 0x57, 0x5b,
+	0x37, 0xb5, 0x9d, 0x6f, 0xa7, 0x9c, 0x93, 0xa3, 0x95, 0x57, 0x4e, 0x67, 0x0f, 0x8d, 0x4c, 0x00,
+	0x1b, 0x30, 0xe8, 0x3e, 0x2c, 0x8c, 0x86, 0x1e, 0x61, 0x34, 0xdd, 0xac, 0xe5, 0x6b, 0xd6, 0xf5,
+	0x62, 0xeb, 0x77, 0xf5, 0xe6, 0xdb, 0xcd, 0x71, 0x4f, 0x8e, 0x56, 0xe6, 0x79, 0xb0, 0x95, 0xee,
+	0x52, 0x3c, 0xd6, 0x1c, 0x25, 0x00, 0x3c, 0xd0, 0x74, 0x18, 0x61, 0xa3, 0xa4, 0x5e, 0x11, 0xa6,
+	0xf8, 0xde, 0x64, 0xee, 0x3a, 0x85, 0xc9, 0xb6, 0x73, 0x46, 0xc3, 0x86, 0x1a, 0xd4, 0x83, 0x72,
+	0xe2, 0x7b, 0xd4, 0x25, 0x71, 0x1d, 0x84, 0xc6, 0x3f, 0x98, 0x4c, 0xa3, 0xc4, 0xc8, 0x56, 0x5c,
+	0x11, 0xb0, 0x46, 0x47, 0x21, 0x2c, 0x8a, 0x95, 0xe4, 0xb3, 0x29, 0x0f, 0xca, 0xa4, 0x5e, 0x13,
+	0x47, 0xd2, 0x99, 0xc1, 0x4d, 0x27, 0x72, 0x49, 0x70, 0x7f, 0xef, 0x09, 0x75, 0x19, 0xa6, 0x5d,
+	0x1a, 0xd3, 0xd0, 0xa5, 0x59, 0x60, 0xbc, 0x31, 0x86, 0x84, 0x4f, 0x61, 0xdb, 0xff, 0x54, 0x82,
+	0xe2, 0x5d, 0x9f, 0x9d, 0x2f, 0x4a, 0x3d, 0x67, 0xc8, 0xa7, 0x32, 0x9c, 0xc2, 0xd9, 0x19, 0x0e,
+	0x22, 0xb0, 0x30, 0x4a, 0x68, 0xcc, 0x37, 0x84, 0xec, 0x85, 0xb0, 0x88, 0x73, 0xc7, 0x10, 0x48,
+	0x18, 0x4d, 0x0e, 0x00, 0x8f, 0x01, 0x72, 0x15, 0x43, 0x92, 0x24, 0x9f, 0x44, 0xb1, 0xa7, 0x54,
+	0x54, 0x2e, 0xac, 0x62, 0x3b, 0x07, 0x80, 0xc7, 0x00, 0xd1, 0x10, 0xae, 0x26, 0x49, 0x7f, 0x3b,
+	0xf6, 0x0f, 0x08, 0xa3, 0xa2, 0xb1, 0xd0, 0x53, 0xbd, 0x50, 0x0e, 0x79, 0x7c, 0xb4, 0x72, 0xd5,
+	0x71, 0x3e, 0x18, 0x47, 0xc1, 0x67, 0x41, 0xa3, 0x6b, 0x50, 0x1a, 0x12, 0xd6, 0x57, 0x47, 0xf2,
+	0x9c, 0x9a, 0xd7, 0xd2, 0x36, 0x61, 0x7d, 0x2c, 0x38, 0xfc, 0x9c, 0xd9, 0x8b, 0x49, 0xe8, 0xf6,
+	0x95, 0xa7, 0x48, 0xcf, 0x99, 0x96, 0xa0, 0x62, 0xc5, 0xd5, 0x51, 0xf7, 0xcc, 0xc5, 0xa3, 0x6e,
+	0xfb, 0xff, 0x2d, 0x98, 0xb9, 0x1b, 0x47, 0xa3, 0x21, 0x5f, 0xe5, 0x7d, 0x7a, 0x38, 0x7e, 0x5c,
+	0xf0, 0x40, 0x8e, 0xd3, 0xf9, 0xa1, 0x49, 0x43, 0xef, 0x7e, 0x57, 0x08, 0x2b, 0x5b, 0x48, 0x77,
+	0xd9, 0x7a, 0xca, 0xc1, 0x86, 0x14, 0x7a, 0x1b, 0x66, 0xbb, 0xd2, 0xd3, 0xc9, 0x31, 0xbe, 0xa2,
+	0xfb, 0x2f, 0xfd, 0xda, 0xc9, 0xd1, 0x4a, 0x4d, 0x08, 0x2a, 0x9f, 0xa7, 0x84, 0x91, 0x0b, 0xe5,
+	0x84, 0x45, 0x31, 0xb7, 0xde, 0xd2, 0x34, 0x9b, 0x53, 0x62, 0x48, 0xa3, 0x56, 0x1f, 0x58, 0x23,
+	0xdb, 0xb3, 0x50, 0xfa, 0x60, 0x67, 0x67, 0xdb, 0xfe, 0x4f, 0x0b, 0x80, 0xff, 0xf8, 0x80, 0x12,
+	0x8f, 0xc6, 0x7c, 0x51, 0xc2, 0xec, 0xbc, 0x48, 0x17, 0x45, 0x9c, 0x13, 0x82, 0x93, 0x45, 0xf7,
+	0x85, 0xf3, 0x46, 0xf7, 0xc5, 0x29, 0xa2, 0xfb, 0xac, 0x6b, 0xea, 0xf0, 0x7f, 0x7e, 0x74, 0x9f,
+	0xc0, 0xe2, 0xb8, 0x34, 0x7a, 0x3c, 0x4d, 0x74, 0x9f, 0x9e, 0x96, 0xbf, 0x26, 0xc2, 0xff, 0x3b,
+	0x0b, 0x2a, 0x5c, 0xab, 0x88, 0xf1, 0x7f, 0x7d, 0x29, 0x04, 0x3d, 0x81, 0x72, 0x5f, 0x74, 0x4e,
+	0x47, 0xe5, 0xef, 0x4d, 0x39, 0x25, 0x99, 0xdf, 0x95, 0xdf, 0x09, 0xd6, 0x0a, 0xec, 0xb6, 0x5c,
+	0x55, 0x35, 0x0d, 0x6f, 0x43, 0x2d, 0xa1, 0xf1, 0x81, 0xef, 0x9a, 0xc1, 0x40, 0x7a, 0x80, 0x3a,
+	0x19, 0x0b, 0x9b, 0x72, 0xf6, 0x5f, 0x5a, 0x50, 0x4d, 0x93, 0x65, 0x6e, 0x1a, 0x5d, 0xbf, 0x1b,
+	0x89, 0xd6, 0x95, 0xcc, 0x34, 0xee, 0x6c, 0xdc, 0xb9, 0x8f, 0x05, 0x07, 0x3d, 0x82, 0x52, 0x9f,
+	0x31, 0x5d, 0x2b, 0xb9, 0x3d, 0xf1, 0xe8, 0x64, 0x5a, 0xcd, 0x7f, 0x61, 0x01, 0xc8, 0x8d, 0x74,
+	0xe6, 0x1e, 0xe9, 0xee, 0x93, 0x73, 0xd8, 0xe7, 0x27, 0x50, 0xdb, 0xe7, 0xa2, 0xed, 0x28, 0xec,
+	0xfa, 0x3d, 0xb5, 0x83, 0xde, 0x9f, 0xa8, 0x2f, 0xf7, 0x32, 0x9c, 0x6c, 0xb6, 0x0c, 0x22, 0x36,
+	0x35, 0xf1, 0x8d, 0xc1, 0xa2, 0xa1, 0xef, 0xaa, 0xcd, 0x9e, 0x6e, 0x8c, 0x1d, 0x4e, 0xc4, 0x92,
+	0x67, 0xff, 0xd4, 0x02, 0x13, 0x81, 0x1f, 0x41, 0x7b, 0x71, 0xb4, 0xcf, 0x6d, 0xc2, 0xca, 0x8e,
+	0xa0, 0x96, 0x24, 0x61, 0xcd, 0xe3, 0x31, 0xd6, 0x01, 0x8d, 0x13, 0x3f, 0x0a, 0xd5, 0xb6, 0x4b,
+	0x57, 0xfe, 0xa1, 0x24, 0x63, 0xcd, 0x47, 0x7f, 0x08, 0xc5, 0x90, 0x32, 0xb5, 0xe9, 0xde, 0x9d,
+	0x7c, 0xdc, 0x5b, 0xeb, 0x3b, 0xad, 0x32, 0xb7, 0xdf, 0xad, 0xf5, 0x1d, 0xcc, 0x21, 0xed, 0x7f,
+	0xb7, 0xa0, 0xa2, 0x59, 0xc8, 0x81, 0x22, 0x0b, 0x12, 0xb5, 0xa1, 0x6e, 0x4d, 0xa4, 0x66, 0xa7,
+	0xe3, 0x48, 0x0d, 0x3b, 0x1d, 0x07, 0x73, 0x34, 0x6e, 0x40, 0x09, 0x49, 0x82, 0xa9, 0x0c, 0xc8,
+	0x69, 0x3a, 0x1d, 0x69, 0x40, 0xfc, 0x17, 0x16, 0x80, 0xf6, 0xdf, 0x5a, 0x50, 0x15, 0x5d, 0x17,
+	0xfb, 0xf4, 0x31, 0xcc, 0x88, 0x85, 0x53, 0xbd, 0xff, 0xfe, 0xe4, 0x93, 0x94, 0xad, 0xb2, 0xf8,
+	0xc4, 0x12, 0x97, 0x9b, 0x02, 0x49, 0x0e, 0x43, 0x57, 0x0c, 0xc4, 0x08, 0xd1, 0x9b, 0x9c, 0x88,
+	0x25, 0xcf, 0xfe, 0x57, 0x6d, 0x0a, 0xa9, 0xaf, 0xfa, 0x86, 0x7b, 0xb5, 0x06, 0xb5, 0x84, 0x91,
+	0x98, 0xc9, 0xa4, 0x57, 0x19, 0x92, 0x9d, 0x7a, 0x81, 0x8c, 0x75, 0xa2, 0xcd, 0x5c, 0x7e, 0x62,
+	0xb3, 0x99, 0xbd, 0x0a, 0xc5, 0x4e, 0xd4, 0x43, 0xd7, 0xa1, 0xc2, 0xe2, 0x51, 0xe8, 0x12, 0x46,
+	0x55, 0xf9, 0x74, 0x8e, 0xe7, 0xe9, 0x3b, 0x8a, 0x86, 0x53, 0xae, 0xfd, 0xe3, 0x22, 0x54, 0x36,
+	0x29, 0x23, 0xbc, 0xc3, 0xe8, 0x2f, 0x2c, 0xa8, 0x91, 0x30, 0x8c, 0x18, 0x91, 0xe5, 0x09, 0x4b,
+	0x38, 0xc2, 0xad, 0x89, 0xc6, 0xaa, 0x41, 0x1b, 0xcd, 0x0c, 0x70, 0x3d, 0x64, 0xf1, 0xa1, 0x51,
+	0x2e, 0xcf, 0x38, 0xd8, 0xd4, 0x8b, 0x9e, 0xc2, 0x6c, 0x40, 0xf6, 0x68, 0xa0, 0x5d, 0xf1, 0xc6,
+	0x74, 0x3d, 0xe8, 0x08, 0x2c, 0xa9, 0xdc, 0xa8, 0x93, 0x71, 0x22, 0x56, 0x8a, 0x96, 0x7e, 0x00,
+	0x8b, 0xe3, 0x1d, 0x45, 0x8b, 0x46, 0xd0, 0x21, 0xe3, 0x8c, 0x97, 0x72, 0xc7, 0xab, 0x3a, 0x4f,
+	0xbf, 0x5f, 0xb8, 0x65, 0x2d, 0xdd, 0x86, 0x9a, 0xa1, 0xe6, 0x22, 0x4d, 0xed, 0x9f, 0x59, 0x50,
+	0xde, 0xa4, 0x2c, 0xf6, 0xdd, 0x44, 0xba, 0x29, 0x46, 0x82, 0xf1, 0xa2, 0xf7, 0x0e, 0x27, 0x62,
+	0xc9, 0xe3, 0x91, 0x17, 0x8d, 0xe3, 0x48, 0x9c, 0x54, 0x5c, 0x2a, 0x1d, 0xd3, 0xba, 0xa0, 0x62,
+	0xc5, 0x45, 0xdb, 0x50, 0x8a, 0xb9, 0x05, 0x14, 0x27, 0xca, 0xa0, 0x53, 0xf7, 0x8d, 0xb9, 0xc5,
+	0x08, 0x24, 0x99, 0x4d, 0xb2, 0xd8, 0xa7, 0x89, 0x70, 0xdd, 0x25, 0x33, 0x9b, 0x14, 0x64, 0xac,
+	0xf9, 0xf6, 0x67, 0x05, 0xa8, 0xe8, 0x44, 0x16, 0xfd, 0x09, 0x54, 0x06, 0x6a, 0x35, 0xd4, 0x06,
+	0x7a, 0xe3, 0x7c, 0xe5, 0x13, 0x99, 0x6d, 0xf0, 0x95, 0xcc, 0xe2, 0xb9, 0x8c, 0x86, 0x53, 0x54,
+	0xe4, 0x42, 0x29, 0x19, 0x52, 0x77, 0xaa, 0x3a, 0x86, 0xee, 0xae, 0x33, 0xa4, 0x6e, 0x36, 0x7c,
+	0x51, 0x10, 0x10, 0xe0, 0x68, 0x1f, 0x66, 0x13, 0x99, 0x09, 0xca, 0x29, 0x6d, 0x4f, 0xa7, 0x46,
+	0x66, 0x83, 0x59, 0x61, 0x5f, 0x66, 0x82, 0x4a, 0x85, 0xfd, 0x85, 0x05, 0x69, 0x25, 0xa0, 0xe3,
+	0x27, 0x0c, 0x7d, 0x7c, 0x6a, 0x12, 0xcf, 0x59, 0x83, 0xe2, 0xad, 0xc5, 0x14, 0xa6, 0x05, 0x3b,
+	0x4d, 0x31, 0x26, 0x70, 0x0f, 0x66, 0x7c, 0x46, 0x07, 0x7a, 0xcb, 0xbd, 0x3b, 0xd5, 0xd0, 0x8c,
+	0x94, 0x8e, 0x63, 0x62, 0x09, 0x6d, 0xff, 0x97, 0x31, 0x24, 0x3e, 0xad, 0x5c, 0xa9, 0xbe, 0xe3,
+	0x99, 0x5c, 0xa9, 0xc8, 0xa2, 0xf9, 0x92, 0x9d, 0x7d, 0x45, 0xd4, 0x83, 0x79, 0x8f, 0x06, 0x94,
+	0xef, 0xeb, 0x35, 0x1a, 0x90, 0xc3, 0x09, 0x2f, 0x8b, 0xae, 0x1c, 0x1f, 0xad, 0xcc, 0xaf, 0x99,
+	0x40, 0x38, 0x8f, 0x6b, 0xff, 0xb4, 0x00, 0x0b, 0xf9, 0xb5, 0x45, 0x6f, 0xc1, 0xcc, 0xb0, 0xaf,
+	0xeb, 0xad, 0xd5, 0xd6, 0xb2, 0xee, 0xe0, 0x36, 0x27, 0x9e, 0x1c, 0xad, 0xcc, 0x6b, 0x79, 0x41,
+	0xc0, 0x52, 0x98, 0xef, 0xb2, 0x01, 0x4d, 0x12, 0x9e, 0x62, 0x8c, 0xc5, 0x13, 0x9b, 0x92, 0x8c,
+	0x35, 0x1f, 0xb9, 0x00, 0x6e, 0x14, 0x7a, 0xbe, 0xf4, 0xd7, 0x45, 0x31, 0x8b, 0xab, 0xe7, 0x1b,
+	0x59, 0x5b, 0xb7, 0xcb, 0x76, 0x56, 0x4a, 0x4a, 0xb0, 0x01, 0x8b, 0x08, 0xd4, 0x02, 0x92, 0x30,
+	0x59, 0x3b, 0xf1, 0x54, 0xd0, 0xf6, 0x7b, 0xe7, 0xd3, 0xb2, 0xe3, 0x0f, 0x68, 0xe6, 0xf1, 0x3b,
+	0x19, 0x0c, 0x36, 0x31, 0xed, 0x9f, 0x17, 0xa0, 0xe0, 0xdc, 0x3c, 0x47, 0x00, 0xc9, 0xb3, 0xce,
+	0x91, 0xbb, 0x4f, 0x4f, 0xdd, 0x7b, 0xb4, 0x04, 0x15, 0x2b, 0x2e, 0x97, 0x8b, 0x69, 0x8f, 0x87,
+	0x64, 0x63, 0xd7, 0x67, 0x58, 0x50, 0xb1, 0xe2, 0xa2, 0x03, 0xa8, 0xb9, 0xd9, 0x35, 0xb0, 0x1a,
+	0xdb, 0x64, 0xfb, 0x3a, 0x7f, 0xa3, 0xdc, 0xba, 0x2c, 0xea, 0x84, 0x19, 0x01, 0x9b, 0x8a, 0xd0,
+	0x13, 0xa8, 0x50, 0x75, 0x49, 0xab, 0x0a, 0xca, 0xef, 0x4f, 0xaa, 0x54, 0x5f, 0xf6, 0xca, 0x33,
+	0x5e, 0x7f, 0xe1, 0x14, 0xdf, 0xfe, 0x11, 0xcc, 0x3a, 0x37, 0x45, 0x6c, 0xe5, 0x40, 0x21, 0xb9,
+	0xa9, 0x06, 0xf9, 0xfb, 0x93, 0x6d, 0xb6, 0x9b, 0x2d, 0x50, 0x53, 0x59, 0x70, 0x6e, 0xe2, 0x42,
+	0x72, 0xd3, 0xfe, 0x0f, 0x0b, 0x2a, 0xce, 0x4d, 0x15, 0x27, 0x49, 0x0d, 0xe5, 0xaf, 0x55, 0x03,
+	0xda, 0x03, 0x18, 0x46, 0x41, 0xb0, 0x4d, 0x63, 0x3f, 0xf2, 0x44, 0xad, 0xf0, 0xe2, 0xfb, 0x37,
+	0x35, 0xf2, 0xed, 0x14, 0x09, 0x1b, 0xa8, 0xf6, 0xff, 0x5a, 0x20, 0x62, 0x52, 0xf4, 0x3e, 0x54,
+	0x07, 0xd4, 0xed, 0x93, 0xd0, 0x4f, 0x06, 0xca, 0x10, 0x75, 0x18, 0x56, 0xdd, 0xd4, 0x0c, 0xbe,
+	0x77, 0xb9, 0x74, 0x4a, 0xc0, 0x59, 0x23, 0xb4, 0x01, 0xa5, 0x51, 0x42, 0xe3, 0x8b, 0x5d, 0xf1,
+	0x8b, 0xba, 0xf9, 0x6e, 0x42, 0x63, 0x55, 0x95, 0x11, 0x10, 0x68, 0x17, 0x2a, 0xba, 0x14, 0xa4,
+	0xce, 0x9c, 0x29, 0xaa, 0x4a, 0x29, 0x94, 0xfd, 0x7f, 0x05, 0xa8, 0xa6, 0xf7, 0x47, 0x68, 0x04,
+	0x55, 0x7e, 0xe6, 0x88, 0xdb, 0x4a, 0x75, 0xb2, 0x34, 0x27, 0xbd, 0x92, 0x72, 0x34, 0x90, 0x91,
+	0xa0, 0x1b, 0x54, 0x9c, 0x69, 0x42, 0x7f, 0x66, 0xc1, 0x62, 0x14, 0x62, 0xea, 0x46, 0xb1, 0xb7,
+	0x15, 0xb1, 0x3b, 0xd1, 0x28, 0xf4, 0xa6, 0x3a, 0xbf, 0xf3, 0xea, 0x8f, 0x8f, 0x56, 0x16, 0xef,
+	0x8f, 0xc1, 0xe3, 0x53, 0x0a, 0x51, 0x1f, 0xca, 0x51, 0x28, 0x02, 0x27, 0x35, 0xc1, 0x5f, 0x83,
+	0x6e, 0x91, 0x26, 0xde, 0x97, 0xa8, 0x58, 0xc3, 0xdb, 0xf7, 0x20, 0x37, 0x15, 0xe8, 0x15, 0x28,
+	0x26, 0x4f, 0x4f, 0x15, 0x24, 0x9c, 0x07, 0x1d, 0xcc, 0xe9, 0xe9, 0x5d, 0x76, 0xe1, 0xac, 0xbb,
+	0x6c, 0xfb, 0xe7, 0x45, 0x28, 0x39, 0x3b, 0xcd, 0xad, 0x73, 0xb8, 0xcc, 0xef, 0x41, 0x39, 0x24,
+	0x2c, 0xd9, 0x8d, 0x03, 0x55, 0xa9, 0x4b, 0x8f, 0x93, 0xad, 0xe6, 0x8e, 0xb3, 0x8b, 0x3b, 0x58,
+	0xf3, 0xd1, 0x5d, 0xb8, 0xc2, 0x7f, 0x6e, 0x46, 0xa1, 0xcf, 0xa2, 0xd8, 0x0f, 0x7b, 0xbc, 0x51,
+	0x45, 0x34, 0xfa, 0xb6, 0x6a, 0x74, 0x85, 0x37, 0x32, 0x04, 0x70, 0x07, 0x9f, 0x6e, 0x83, 0x56,
+	0xa1, 0xaa, 0x6e, 0x45, 0x36, 0x3c, 0x75, 0x25, 0x90, 0xde, 0x53, 0xa8, 0xbb, 0x93, 0x8d, 0x35,
+	0x9c, 0xc9, 0xf0, 0x4e, 0x26, 0x23, 0x11, 0xd8, 0x29, 0x87, 0x9d, 0x55, 0xad, 0x25, 0x19, 0x6b,
+	0x3e, 0xea, 0xc0, 0xbc, 0xfa, 0xb9, 0x1d, 0xd3, 0xae, 0xff, 0x4c, 0x5d, 0x1e, 0x7c, 0x57, 0x35,
+	0x98, 0x77, 0x4c, 0xe6, 0xc9, 0x38, 0x01, 0xe7, 0x1b, 0xa3, 0x8f, 0xa0, 0x44, 0x46, 0xac, 0xaf,
+	0x5c, 0xd6, 0x84, 0x11, 0xc8, 0x4e, 0x73, 0xab, 0x39, 0x62, 0x7d, 0xb5, 0x4a, 0x23, 0xd6, 0xc7,
+	0x02, 0x14, 0xbd, 0x0d, 0xb5, 0x01, 0x79, 0xb6, 0x11, 0x76, 0x03, 0xbf, 0xd7, 0x97, 0xf5, 0xda,
+	0xf9, 0xec, 0x34, 0xdc, 0xcc, 0x58, 0xd8, 0x94, 0xb3, 0x31, 0x54, 0x34, 0x24, 0xba, 0xc3, 0x33,
+	0x82, 0x7d, 0x1a, 0x5e, 0xac, 0x3a, 0x56, 0x95, 0x49, 0xc3, 0x3e, 0x0d, 0xb1, 0x6c, 0x6e, 0xff,
+	0x9b, 0x05, 0x33, 0x8e, 0x4b, 0x02, 0x8a, 0x9a, 0x70, 0xd9, 0xa3, 0x89, 0x1f, 0x53, 0x4f, 0x5d,
+	0x01, 0x25, 0xca, 0x78, 0xd2, 0x57, 0x46, 0x6b, 0x79, 0x36, 0x1e, 0x97, 0xe7, 0xcb, 0x3b, 0xa4,
+	0x74, 0x3f, 0x8b, 0xa7, 0x8c, 0xe5, 0xdd, 0xd6, 0x0c, 0x9c, 0xc9, 0xa0, 0x5b, 0x30, 0x97, 0xb8,
+	0x24, 0xf0, 0xc3, 0x9e, 0x6c, 0x33, 0x76, 0xd3, 0xeb, 0x18, 0x3c, 0x9c, 0x93, 0xb4, 0x3d, 0xd0,
+	0xf7, 0x16, 0xf9, 0x47, 0x18, 0xd6, 0xd7, 0xfa, 0x08, 0xe3, 0xb3, 0x12, 0x94, 0xc4, 0x09, 0xf9,
+	0x9b, 0xb7, 0xd3, 0x23, 0x28, 0x25, 0x8c, 0x84, 0xd3, 0x95, 0x41, 0x76, 0x9a, 0x5b, 0xaa, 0x0c,
+	0xb2, 0xd3, 0xdc, 0xc2, 0x02, 0x30, 0x2b, 0x31, 0x4c, 0xf3, 0x7c, 0x26, 0xad, 0xa3, 0x48, 0x13,
+	0xc8, 0x95, 0x18, 0x1c, 0x28, 0x06, 0x91, 0x2e, 0xba, 0x4d, 0x56, 0x15, 0xea, 0x44, 0x3d, 0x59,
+	0x15, 0xea, 0x44, 0x3d, 0xcc, 0xd1, 0xf8, 0xfe, 0x11, 0x65, 0xc5, 0x99, 0x29, 0xf6, 0x8f, 0xae,
+	0xd1, 0x8e, 0x97, 0x16, 0x55, 0x34, 0x21, 0x0f, 0xfc, 0x77, 0x26, 0x8c, 0x26, 0x04, 0xf0, 0xac,
+	0x11, 0x4d, 0x38, 0x50, 0xf0, 0xf6, 0xd4, 0x7e, 0x7f, 0x67, 0xc2, 0x0b, 0xef, 0x0c, 0x74, 0xad,
+	0x85, 0x0b, 0xde, 0x9e, 0xfd, 0xcf, 0x33, 0xa0, 0x5e, 0x66, 0x9d, 0xcf, 0x84, 0xdc, 0x38, 0x9a,
+	0xce, 0x84, 0xda, 0x71, 0x14, 0xca, 0xf9, 0xe2, 0xbf, 0xb0, 0x00, 0x4c, 0x6d, 0xb3, 0xf8, 0x75,
+	0xdb, 0x26, 0xd1, 0xb6, 0x39, 0x75, 0xc5, 0x56, 0xdd, 0x14, 0x9c, 0xb6, 0xce, 0x1f, 0xe5, 0x0c,
+	0x69, 0xf2, 0xea, 0xbb, 0x52, 0x30, 0x6e, 0x4a, 0xbb, 0xc2, 0x94, 0x2a, 0xd3, 0x78, 0x79, 0x15,
+	0xe3, 0xe6, 0x8c, 0x69, 0x57, 0x18, 0xd3, 0xec, 0x34, 0xcf, 0x69, 0x5a, 0x26, 0xac, 0x34, 0x27,
+	0x3e, 0xdf, 0x31, 0x65, 0xf1, 0xa1, 0x32, 0xd3, 0xc9, 0xee, 0x98, 0xd4, 0xcb, 0xce, 0x2c, 0x2f,
+	0xc6, 0x1c, 0x12, 0x4b, 0x64, 0xfb, 0xbf, 0x0b, 0x30, 0x27, 0x35, 0xab, 0x64, 0xf5, 0x55, 0x28,
+	0x0f, 0x69, 0xe8, 0xf9, 0x61, 0x4f, 0xd8, 0x4f, 0x49, 0x86, 0x31, 0xdb, 0x92, 0x84, 0x35, 0x0f,
+	0xbd, 0x29, 0xb3, 0x41, 0x45, 0x17, 0xcb, 0x55, 0x92, 0xc9, 0x4e, 0x27, 0x23, 0x63, 0x53, 0x06,
+	0x1d, 0xf2, 0x84, 0x56, 0x14, 0xb8, 0xea, 0xa5, 0x29, 0x4a, 0x8a, 0x66, 0x6f, 0x1b, 0xaa, 0x62,
+	0x26, 0xab, 0x7a, 0x46, 0x82, 0x2c, 0xa8, 0x58, 0xeb, 0x5b, 0x7a, 0x06, 0x73, 0xa6, 0xe4, 0x19,
+	0x85, 0x39, 0x6c, 0x16, 0xe6, 0x26, 0x9d, 0x6a, 0xad, 0xd7, 0x28, 0xeb, 0xfd, 0x4b, 0x01, 0x4a,
+	0x0e, 0xa3, 0xc3, 0x17, 0x50, 0xfc, 0x7a, 0x9c, 0x2b, 0x7e, 0x4d, 0x59, 0x45, 0x39, 0xab, 0xf0,
+	0xd5, 0x1b, 0x2b, 0x7c, 0x4d, 0xfd, 0x04, 0xe2, 0x79, 0x45, 0xaf, 0xcf, 0x79, 0x2e, 0xc9, 0xe8,
+	0xf0, 0x05, 0x14, 0xbc, 0xfe, 0x38, 0x5f, 0xf0, 0xba, 0x3d, 0xf1, 0x90, 0x9e, 0x53, 0xec, 0xfa,
+	0xf4, 0x8a, 0x1c, 0x8a, 0x28, 0x74, 0xe9, 0x33, 0x61, 0xf6, 0xb9, 0x67, 0x82, 0x03, 0x45, 0x97,
+	0xb0, 0xfa, 0xe5, 0x29, 0x0e, 0xe7, 0x36, 0x61, 0xf2, 0x70, 0x6e, 0x13, 0x86, 0x39, 0x1a, 0xda,
+	0x87, 0xaa, 0xab, 0xdf, 0x06, 0xab, 0x29, 0x9c, 0x2c, 0xac, 0x48, 0x5f, 0x18, 0xcb, 0x2b, 0xde,
+	0xf4, 0x13, 0x67, 0xf8, 0xe8, 0x31, 0xcc, 0x7a, 0xe2, 0x71, 0x57, 0xfd, 0xb7, 0xa7, 0x39, 0x5b,
+	0x05, 0x44, 0x0b, 0xc4, 0x8b, 0x35, 0xf1, 0x1b, 0x2b, 0x58, 0xae, 0x80, 0x8a, 0x97, 0x5b, 0xf5,
+	0xa5, 0x29, 0x14, 0xc8, 0xc7, 0x5f, 0x52, 0x81, 0xfc, 0x8d, 0x15, 0x2c, 0x7a, 0x03, 0x66, 0xbb,
+	0x7e, 0xc0, 0x68, 0xac, 0x72, 0x9e, 0x7a, 0xfa, 0x24, 0x40, 0x50, 0x4f, 0xd2, 0x5f, 0x58, 0xc9,
+	0x21, 0x17, 0xca, 0x5d, 0xf9, 0x84, 0xac, 0xfe, 0xed, 0x29, 0xdc, 0x87, 0x7a, 0x86, 0x26, 0x3d,
+	0xae, 0xfa, 0xc0, 0x1a, 0x99, 0x9b, 0x46, 0xcf, 0x67, 0xe2, 0x45, 0xd9, 0xa4, 0xa6, 0x71, 0xd7,
+	0x57, 0xa6, 0x71, 0xd7, 0x67, 0x98, 0xa3, 0xa1, 0x8f, 0x60, 0xa6, 0x27, 0x5e, 0x4b, 0xd4, 0xa6,
+	0xb8, 0xd0, 0x12, 0x0f, 0x24, 0xe4, 0x59, 0x2e, 0x1f, 0x58, 0x48, 0x4c, 0x11, 0xe0, 0x44, 0x1e,
+	0x55, 0xa7, 0xd7, 0x84, 0x01, 0x4e, 0xe4, 0xa9, 0x53, 0x9c, 0xff, 0xc2, 0x02, 0x10, 0xfd, 0x0e,
+	0x14, 0x07, 0x64, 0xa8, 0x5e, 0xe3, 0x69, 0xa7, 0x58, 0xdc, 0x24, 0xc3, 0x13, 0xf9, 0x07, 0x73,
+	0x36, 0x7a, 0x0d, 0x2a, 0xb1, 0x4e, 0x6d, 0xbe, 0x25, 0x72, 0xae, 0xd4, 0x11, 0xa4, 0x39, 0x4d,
+	0x2a, 0xc1, 0xe3, 0x6e, 0x9e, 0x71, 0xd0, 0x7a, 0x7d, 0x8a, 0x99, 0x10, 0xa9, 0x95, 0x51, 0x81,
+	0xe6, 0x9f, 0x58, 0xe2, 0xa2, 0x2e, 0x94, 0x75, 0xd6, 0x22, 0x2b, 0xb4, 0xef, 0x4c, 0x71, 0xfc,
+	0x19, 0x89, 0xb1, 0x4a, 0x63, 0x34, 0x38, 0xf7, 0x68, 0x89, 0x1f, 0xee, 0xeb, 0x43, 0x76, 0x42,
+	0x8f, 0xc6, 0x23, 0xdb, 0x6c, 0x1c, 0x1c, 0x0f, 0x4b, 0x58, 0xf4, 0x18, 0xe6, 0x63, 0x2a, 0x6e,
+	0x1b, 0xd5, 0xab, 0x3d, 0x99, 0xd8, 0xdf, 0xd6, 0x89, 0x37, 0x36, 0x99, 0x27, 0x47, 0x2b, 0xd7,
+	0xce, 0x78, 0xb8, 0x97, 0x93, 0xc1, 0x79, 0x3c, 0x74, 0x03, 0x80, 0xd1, 0x78, 0xe0, 0x87, 0x84,
+	0x45, 0xf2, 0xed, 0x9b, 0xf1, 0xf6, 0x75, 0x27, 0xe5, 0x60, 0x43, 0x0a, 0xad, 0x43, 0x59, 0xfe,
+	0x07, 0x42, 0x52, 0x9f, 0x7f, 0xfe, 0x13, 0x23, 0xf9, 0x2f, 0x0b, 0xc6, 0xc5, 0xbc, 0x6c, 0x82,
+	0x75, 0x5b, 0xf4, 0x43, 0x40, 0xea, 0x71, 0x45, 0xd3, 0x75, 0xa3, 0x51, 0xc8, 0xc4, 0x5b, 0x8c,
+	0x85, 0xdc, 0xff, 0x6b, 0x20, 0xe7, 0x94, 0x04, 0x3e, 0xa3, 0x15, 0xea, 0x19, 0xe7, 0xd6, 0xe2,
+	0x14, 0x47, 0xb2, 0xbe, 0xc0, 0x94, 0x85, 0x5d, 0xfd, 0x65, 0x1c, 0x61, 0x7f, 0x65, 0xc1, 0x5c,
+	0x18, 0x79, 0x54, 0xa7, 0xfd, 0xf5, 0x2b, 0x62, 0x06, 0xee, 0x4f, 0x15, 0x00, 0x34, 0xb6, 0x0c,
+	0x44, 0x19, 0x5e, 0xa5, 0x79, 0xba, 0xc9, 0xc2, 0x39, 0xd5, 0xe8, 0x0e, 0x54, 0x48, 0xb7, 0xeb,
+	0x87, 0x3e, 0x3b, 0xac, 0x23, 0x31, 0xe8, 0x97, 0xcf, 0x5a, 0x88, 0xa6, 0x92, 0x91, 0x63, 0xd2,
+	0x5f, 0x38, 0x6d, 0x8b, 0x76, 0xa1, 0xc6, 0xa2, 0x80, 0xc6, 0xea, 0x0a, 0xfa, 0xaa, 0x18, 0xd1,
+	0xf2, 0x59, 0x50, 0x3b, 0xa9, 0x58, 0x56, 0x52, 0xc9, 0x68, 0x09, 0x36, 0x71, 0xcc, 0x37, 0x95,
+	0x2f, 0xbf, 0xf0, 0x37, 0x95, 0x2f, 0x7d, 0x73, 0x6f, 0x2a, 0x97, 0xde, 0x83, 0x2b, 0xa7, 0x16,
+	0xec, 0x42, 0xd7, 0xcf, 0xff, 0x50, 0x06, 0xe3, 0x21, 0x2a, 0x7a, 0x23, 0x7f, 0x65, 0xb5, 0x34,
+	0x7e, 0x65, 0x55, 0xe5, 0xb2, 0xb9, 0xeb, 0x2a, 0x71, 0xd5, 0x42, 0x92, 0x28, 0x54, 0xa7, 0xa6,
+	0x71, 0xd5, 0xc2, 0xa9, 0x58, 0x71, 0x2f, 0x72, 0xad, 0x65, 0x3a, 0xf0, 0x99, 0xdf, 0xe8, 0xc0,
+	0x5f, 0x83, 0x4a, 0xa2, 0x77, 0x40, 0x79, 0xec, 0x3f, 0x67, 0xb4, 0xb1, 0xa6, 0x12, 0xc8, 0x83,
+	0x39, 0x9e, 0x9b, 0x08, 0x0f, 0xed, 0x35, 0x99, 0xca, 0xdd, 0x2e, 0x72, 0x9d, 0x95, 0x6e, 0x87,
+	0x8e, 0x81, 0x83, 0x73, 0xa8, 0xe8, 0x53, 0x0b, 0x16, 0x12, 0x23, 0x5f, 0x49, 0x7d, 0xbf, 0x33,
+	0x65, 0xe8, 0x9c, 0xcb, 0x82, 0xa8, 0xca, 0x7f, 0xae, 0xeb, 0xf7, 0xcd, 0x79, 0xe6, 0xc9, 0x29,
+	0x0a, 0x1e, 0xeb, 0x14, 0xfa, 0x7b, 0x0b, 0xe6, 0xb8, 0x77, 0x4f, 0x7b, 0x29, 0xcf, 0x8e, 0x07,
+	0x53, 0xf7, 0xd2, 0xc0, 0x94, 0x7d, 0x7c, 0x35, 0x7d, 0xcb, 0xa2, 0x59, 0x67, 0x76, 0x30, 0xd7,
+	0x9b, 0xa5, 0x3f, 0xb7, 0xe0, 0xea, 0x19, 0x03, 0x3e, 0xc3, 0xc0, 0x1f, 0xe5, 0xd3, 0xb8, 0xe6,
+	0xd4, 0x19, 0xa6, 0xf9, 0xba, 0xe3, 0x27, 0x16, 0x5c, 0x39, 0x35, 0xa2, 0x17, 0xdc, 0x09, 0xfb,
+	0x21, 0xe8, 0x87, 0xa2, 0xe7, 0x2b, 0xfa, 0x27, 0xa3, 0xbd, 0x6d, 0xc2, 0xfa, 0xe3, 0x9b, 0xcd,
+	0x91, 0x64, 0xac, 0xf9, 0xf6, 0x5f, 0x17, 0xa0, 0xb8, 0xd3, 0x71, 0xd0, 0x47, 0x30, 0xe7, 0x92,
+	0x36, 0x8d, 0x99, 0x7a, 0x5d, 0x7c, 0xf1, 0x7f, 0xb6, 0x6a, 0x37, 0xb3, 0xe6, 0x38, 0x07, 0x86,
+	0x76, 0x01, 0xdc, 0x0c, 0xfa, 0xe2, 0x37, 0x63, 0x06, 0xb0, 0x01, 0x84, 0x30, 0x54, 0xf7, 0xd3,
+	0xe7, 0xd0, 0x17, 0xba, 0x20, 0x13, 0x79, 0x4c, 0xf6, 0x08, 0x3a, 0x83, 0x69, 0x35, 0x3e, 0xff,
+	0x6a, 0xf9, 0xd2, 0x17, 0x5f, 0x2d, 0x5f, 0xfa, 0xf2, 0xab, 0xe5, 0x4b, 0x3f, 0x3e, 0x5e, 0xb6,
+	0x3e, 0x3f, 0x5e, 0xb6, 0xbe, 0x38, 0x5e, 0xb6, 0xbe, 0x3c, 0x5e, 0xb6, 0x7e, 0x71, 0xbc, 0x6c,
+	0xfd, 0xcd, 0x2f, 0x97, 0x2f, 0xfd, 0x51, 0x45, 0xaf, 0xd7, 0xaf, 0x02, 0x00, 0x00, 0xff, 0xff,
+	0x5f, 0xe0, 0x17, 0x94, 0x87, 0x3d, 0x00, 0x00,
 }
 
 func (m *AWSCredentials) Marshal() (dAtA []byte, err error) {
@@ -4264,17 +4265,21 @@ func (m *Scale) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
-	i = encodeVarintGenerated(dAtA, i, uint64(m.ReplicaRatio))
+	i -= len(m.ScalingDelay)
+	copy(dAtA[i:], m.ScalingDelay)
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.ScalingDelay)))
 	i--
-	dAtA[i] = 0x18
-	if m.MaxReplicas != nil {
-		i = encodeVarintGenerated(dAtA, i, uint64(*m.MaxReplicas))
-		i--
-		dAtA[i] = 0x10
-	}
-	i = encodeVarintGenerated(dAtA, i, uint64(m.MinReplicas))
+	dAtA[i] = 0x1a
+	i -= len(m.PeekDelay)
+	copy(dAtA[i:], m.PeekDelay)
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.PeekDelay)))
 	i--
-	dAtA[i] = 0x8
+	dAtA[i] = 0x12
+	i -= len(m.DesiredReplicas)
+	copy(dAtA[i:], m.DesiredReplicas)
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.DesiredReplicas)))
+	i--
+	dAtA[i] = 0xa
 	return len(dAtA) - i, nil
 }
 
@@ -4541,6 +4546,11 @@ func (m *SourceStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	if m.LastPending != nil {
+		i = encodeVarintGenerated(dAtA, i, uint64(*m.LastPending))
+		i--
+		dAtA[i] = 0x28
+	}
 	if len(m.Metrics) > 0 {
 		keysForMetrics := make([]string, 0, len(m.Metrics))
 		for k := range m.Metrics {
@@ -4752,20 +4762,18 @@ func (m *StepSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i--
 		dAtA[i] = 0xca
 	}
-	if m.Scale != nil {
-		{
-			size, err := m.Scale.MarshalToSizedBuffer(dAtA[:i])
-			if err != nil {
-				return 0, err
-			}
-			i -= size
-			i = encodeVarintGenerated(dAtA, i, uint64(size))
+	{
+		size, err := m.Scale.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
 		}
-		i--
-		dAtA[i] = 0x1
-		i--
-		dAtA[i] = 0xc2
+		i -= size
+		i = encodeVarintGenerated(dAtA, i, uint64(size))
 	}
+	i--
+	dAtA[i] = 0x1
+	i--
+	dAtA[i] = 0xc2
 	i = encodeVarintGenerated(dAtA, i, uint64(m.Replicas))
 	i--
 	dAtA[i] = 0x1
@@ -5961,11 +5969,12 @@ func (m *Scale) Size() (n int) {
 	}
 	var l int
 	_ = l
-	n += 1 + sovGenerated(uint64(m.MinReplicas))
-	if m.MaxReplicas != nil {
-		n += 1 + sovGenerated(uint64(*m.MaxReplicas))
-	}
-	n += 1 + sovGenerated(uint64(m.ReplicaRatio))
+	l = len(m.DesiredReplicas)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.PeekDelay)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.ScalingDelay)
+	n += 1 + l + sovGenerated(uint64(l))
 	return n
 }
 
@@ -6070,6 +6079,9 @@ func (m *SourceStatus) Size() (n int) {
 			n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize))
 		}
 	}
+	if m.LastPending != nil {
+		n += 1 + sovGenerated(uint64(*m.LastPending))
+	}
 	return n
 }
 
@@ -6189,10 +6201,8 @@ func (m *StepSpec) Size() (n int) {
 		}
 	}
 	n += 2 + sovGenerated(uint64(m.Replicas))
-	if m.Scale != nil {
-		l = m.Scale.Size()
-		n += 2 + l + sovGenerated(uint64(l))
-	}
+	l = m.Scale.Size()
+	n += 2 + l + sovGenerated(uint64(l))
 	if m.Flatten != nil {
 		l = m.Flatten.Size()
 		n += 2 + l + sovGenerated(uint64(l))
@@ -6968,9 +6978,9 @@ func (this *Scale) String() string {
 	}
 	s := strings.Join([]string{
 		`&Scale{`,
-		`MinReplicas:` + fmt.Sprintf("%v", this.MinReplicas) + `,`,
-		`MaxReplicas:` + valueToStringGenerated(this.MaxReplicas) + `,`,
-		`ReplicaRatio:` + fmt.Sprintf("%v", this.ReplicaRatio) + `,`,
+		`DesiredReplicas:` + fmt.Sprintf("%v", this.DesiredReplicas) + `,`,
+		`PeekDelay:` + fmt.Sprintf("%v", this.PeekDelay) + `,`,
+		`ScalingDelay:` + fmt.Sprintf("%v", this.ScalingDelay) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -7043,6 +7053,7 @@ func (this *SourceStatus) String() string {
 		`&SourceStatus{`,
 		`Pending:` + valueToStringGenerated(this.Pending) + `,`,
 		`Metrics:` + mapStringForMetrics + `,`,
+		`LastPending:` + valueToStringGenerated(this.LastPending) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -7141,7 +7152,7 @@ func (this *StepSpec) String() string {
 		`Tolerations:` + repeatedStringForTolerations + `,`,
 		`ImagePullSecrets:` + repeatedStringForImagePullSecrets + `,`,
 		`Replicas:` + fmt.Sprintf("%v", this.Replicas) + `,`,
-		`Scale:` + strings.Replace(this.Scale.String(), "Scale", "Scale", 1) + `,`,
+		`Scale:` + strings.Replace(strings.Replace(this.Scale.String(), "Scale", "Scale", 1), `&`, ``, 1) + `,`,
 		`Flatten:` + strings.Replace(this.Flatten.String(), "Flatten", "Flatten", 1) + `,`,
 		`Expand:` + strings.Replace(this.Expand.String(), "Expand", "Expand", 1) + `,`,
 		`Dedupe:` + strings.Replace(this.Dedupe.String(), "Dedupe", "Dedupe", 1) + `,`,
@@ -13581,10 +13592,10 @@ func (m *Scale) Unmarshal(dAtA []byte) error {
 		}
 		switch fieldNum {
 		case 1:
-			if wireType != 0 {
-				return fmt.Errorf("proto: wrong wireType = %d for field MinReplicas", wireType)
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field DesiredReplicas", wireType)
 			}
-			m.MinReplicas = 0
+			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowGenerated
@@ -13594,16 +13605,29 @@ func (m *Scale) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				m.MinReplicas |= int32(b&0x7F) << shift
+				stringLen |= uint64(b&0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.DesiredReplicas = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		case 2:
-			if wireType != 0 {
-				return fmt.Errorf("proto: wrong wireType = %d for field MaxReplicas", wireType)
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PeekDelay", wireType)
 			}
-			var v uint32
+			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowGenerated
@@ -13613,17 +13637,29 @@ func (m *Scale) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				v |= uint32(b&0x7F) << shift
+				stringLen |= uint64(b&0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
-			m.MaxReplicas = &v
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.PeekDelay = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		case 3:
-			if wireType != 0 {
-				return fmt.Errorf("proto: wrong wireType = %d for field ReplicaRatio", wireType)
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ScalingDelay", wireType)
 			}
-			m.ReplicaRatio = 0
+			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowGenerated
@@ -13633,11 +13669,24 @@ func (m *Scale) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				m.ReplicaRatio |= uint32(b&0x7F) << shift
+				stringLen |= uint64(b&0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ScalingDelay = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -14553,6 +14602,26 @@ func (m *SourceStatus) Unmarshal(dAtA []byte) error {
 			}
 			m.Metrics[mapkey] = *mapvalue
 			iNdEx = postIndex
+		case 5:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field LastPending", wireType)
+			}
+			var v uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.LastPending = &v
 		default:
 			iNdEx = preIndex
 			skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -15649,9 +15718,6 @@ func (m *StepSpec) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			if m.Scale == nil {
-				m.Scale = &Scale{}
-			}
 			if err := m.Scale.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
diff --git a/api/v1alpha1/generated.proto b/api/v1alpha1/generated.proto
index 0363e70a..00f65b63 100644
--- a/api/v1alpha1/generated.proto
+++ b/api/v1alpha1/generated.proto
@@ -409,12 +409,16 @@ message STANAuth {
 }
 
 message Scale {
-  optional int32 minReplicas = 1;
+  // An expression to determine the number of replicas. Must evaluation to an `int`.
+  optional string desiredReplicas = 1;
 
-  optional uint32 maxReplicas = 2;
+  // An expression to determine the delay for peeking. Maybe string or duration, e.g. `"4m"`
+  // +kubebuilder:default="defaultPeekDelay"
+  optional string peekDelay = 2;
 
-  // takes precedence over min
-  optional uint32 replicaRatio = 3;
+  // An expression to determine the delay for scaling. Maybe string or duration, e.g. `"1m"`
+  // +kubebuilder:default="defaultScalingDelay"
+  optional string scalingDelay = 3;
 }
 
 message Sidecar {
@@ -462,6 +466,8 @@ message Source {
 message SourceStatus {
   optional uint64 pending = 3;
 
+  optional uint64 lastPending = 5;
+
   map<string, Metrics> metrics = 4;
 }
 
@@ -514,6 +520,7 @@ message StepSpec {
   // +kubebuilder:default=1
   optional uint32 replicas = 23;
 
+  // +kubebuilder:default={peekDelay: "defaultPeekDelay", scalingDelay: "defaultScalingDelay", desiredReplicas: ""}
   optional Scale scale = 24;
 
   // +patchStrategy=merge
diff --git a/api/v1alpha1/scale.go b/api/v1alpha1/scale.go
index 1311f95e..2a832482 100644
--- a/api/v1alpha1/scale.go
+++ b/api/v1alpha1/scale.go
@@ -1,31 +1,12 @@
 package v1alpha1
 
 type Scale struct {
-	MinReplicas  int32   `json:"minReplicas" protobuf:"varint,1,opt,name=minReplicas"`
-	MaxReplicas  *uint32 `json:"maxReplicas,omitempty" protobuf:"varint,2,opt,name=maxReplicas"` // takes precedence over min
-	ReplicaRatio uint32  `json:"replicaRatio,omitempty" protobuf:"varint,3,opt,name=replicaRatio"`
-}
-
-// Used to calculate the number of replicas.
-// min(r.max, max(r.min, pending/ratio))
-// Example:
-// min=1, max=4, ratio=100
-// pending=0, replicas=1
-// pending=100, replicas=1
-// pending=200, replicas=2
-// pending=300, replicas=3
-// pending=400, replicas=4
-// pending=500, replicas=4
-func (in Scale) Calculate(pending int) int {
-	n := 0
-	if in.ReplicaRatio > 0 {
-		n = pending / int(in.ReplicaRatio)
-	}
-	if n < int(in.MinReplicas) {
-		n = int(in.MinReplicas)
-	}
-	if in.MaxReplicas != nil && n > int(*in.MaxReplicas) {
-		n = int(*in.MaxReplicas)
-	}
-	return n
+	// An expression to determine the number of replicas. Must evaluation to an `int`.
+	DesiredReplicas string `json:"desiredReplicas,omitempty" protobuf:"bytes,1,opt,name=desiredReplicas"`
+	// An expression to determine the delay for peeking. Maybe string or duration, e.g. `"4m"`
+	// +kubebuilder:default="defaultPeekDelay"
+	PeekDelay string `json:"peekDelay,omitempty" protobuf:"bytes,2,opt,name=peekDelay"`
+	// An expression to determine the delay for scaling. Maybe string or duration, e.g. `"1m"`
+	// +kubebuilder:default="defaultScalingDelay"
+	ScalingDelay string `json:"scalingDelay,omitempty" protobuf:"bytes,3,opt,name=scalingDelay"`
 }
diff --git a/api/v1alpha1/source_status.go b/api/v1alpha1/source_status.go
index a4267592..8c65c5a1 100644
--- a/api/v1alpha1/source_status.go
+++ b/api/v1alpha1/source_status.go
@@ -1,8 +1,9 @@
 package v1alpha1
 
 type SourceStatus struct {
-	Pending *uint64            `json:"pending,omitempty" protobuf:"varint,3,opt,name=pending"`
-	Metrics map[string]Metrics `json:"metrics,omitempty" protobuf:"bytes,4,rep,name=metrics"`
+	Pending     *uint64            `json:"pending,omitempty" protobuf:"varint,3,opt,name=pending"`
+	LastPending *uint64            `json:"lastPending,omitempty" protobuf:"varint,5,opt,name=lastPending"`
+	Metrics     map[string]Metrics `json:"metrics,omitempty" protobuf:"bytes,4,rep,name=metrics"`
 }
 
 // GetPending returns pending counts
@@ -21,6 +22,10 @@ func (in SourceStatus) GetTotal() uint64 {
 	return x
 }
 
+func (in SourceStatus) GetLeaderTotal() uint64 {
+	return in.Metrics["0"].Total
+}
+
 func (in SourceStatus) GetErrors() uint64 {
 	var x uint64
 	for _, m := range in.Metrics {
diff --git a/api/v1alpha1/source_statuses.go b/api/v1alpha1/source_statuses.go
index 13adcf45..5776b8d4 100644
--- a/api/v1alpha1/source_statuses.go
+++ b/api/v1alpha1/source_statuses.go
@@ -40,6 +40,7 @@ func (in SourceStatuses) IncrErrors(name string, replica int) {
 
 func (in SourceStatuses) SetPending(name string, pending uint64) {
 	x := in[name]
+	x.LastPending = x.Pending
 	x.Pending = &pending
 	in[name] = x
 }
@@ -54,6 +55,16 @@ func (in SourceStatuses) GetPending() uint64 {
 	return v
 }
 
+func (in SourceStatuses) GetLastPending() uint64 {
+	var v uint64
+	for _, s := range in {
+		if s.LastPending != nil {
+			v += *s.LastPending
+		}
+	}
+	return v
+}
+
 func (in SourceStatuses) GetErrors() uint64 {
 	var v uint64
 	for _, s := range in {
diff --git a/api/v1alpha1/step_spec.go b/api/v1alpha1/step_spec.go
index 497938a0..6f76e220 100644
--- a/api/v1alpha1/step_spec.go
+++ b/api/v1alpha1/step_spec.go
@@ -21,7 +21,8 @@ type StepSpec struct {
 
 	// +kubebuilder:default=1
 	Replicas uint32 `json:"replicas,omitempty" protobuf:"varint,23,opt,name=replicas"`
-	Scale    *Scale `json:"scale,omitempty" protobuf:"bytes,24,opt,name=scale"`
+	// +kubebuilder:default={peekDelay: "defaultPeekDelay", scalingDelay: "defaultScalingDelay", desiredReplicas: ""}
+	Scale Scale `json:"scale,omitempty" protobuf:"bytes,24,opt,name=scale"`
 	// +patchStrategy=merge
 	// +patchMergeKey=name
 	Sources Sources `json:"sources,omitempty" protobuf:"bytes,3,rep,name=sources"`
@@ -84,13 +85,6 @@ func (in StepSpec) getType() containerSupplier {
 	}
 }
 
-func (in StepSpec) CalculateReplicas(pending int) int {
-	if in.Scale == nil {
-		return -1
-	}
-	return in.Scale.Calculate(pending)
-}
-
 func (in StepSpec) WithOutReplicas() StepSpec {
 	x := *in.DeepCopy()
 	x.Replicas = 0
diff --git a/api/v1alpha1/step_types.go b/api/v1alpha1/step_types.go
index 15fd5d04..5680585a 100644
--- a/api/v1alpha1/step_types.go
+++ b/api/v1alpha1/step_types.go
@@ -20,7 +20,6 @@ import (
 	"encoding/json"
 	"os"
 	"strconv"
-	"time"
 
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
@@ -157,41 +156,6 @@ func (in Step) withoutManagedFields() Step {
 	return y
 }
 
-func (in Step) GetTargetReplicas(scalingDelay, peekDelay time.Duration) int {
-	currentReplicas := int(in.Status.Replicas)
-	lastScaledAt := in.Status.LastScaledAt.Time
-
-	if time.Since(lastScaledAt) < scalingDelay {
-		return currentReplicas
-	}
-
-	pending := in.Status.SourceStatuses.GetPending()
-	targetReplicas := in.Spec.CalculateReplicas(int(pending))
-	if targetReplicas == -1 {
-		return currentReplicas
-	}
-
-	// do we need to peek? currentReplicas and targetReplicas must both be zero
-	if currentReplicas <= 0 && targetReplicas == 0 && time.Since(lastScaledAt) > peekDelay {
-		return 1
-	}
-	// prevent violent scale-up and scale-down by only scaling by 1 each time
-	if targetReplicas > currentReplicas {
-		return currentReplicas + 1
-	} else if targetReplicas < currentReplicas {
-		return currentReplicas - 1
-	} else {
-		return targetReplicas
-	}
-}
-
-func RequeueAfter(currentReplicas, targetReplicas int, scalingDelay time.Duration) time.Duration {
-	if currentReplicas <= 0 && targetReplicas == 0 {
-		return scalingDelay
-	}
-	return 0
-}
-
 // +kubebuilder:object:root=true
 
 type StepList struct {
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 4eff03b2..ef41bff0 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -948,11 +948,6 @@ func (in *STANAuth) DeepCopy() *STANAuth {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Scale) DeepCopyInto(out *Scale) {
 	*out = *in
-	if in.MaxReplicas != nil {
-		in, out := &in.MaxReplicas, &out.MaxReplicas
-		*out = new(uint32)
-		**out = **in
-	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Scale.
@@ -1080,6 +1075,11 @@ func (in *SourceStatus) DeepCopyInto(out *SourceStatus) {
 		*out = new(uint64)
 		**out = **in
 	}
+	if in.LastPending != nil {
+		in, out := &in.LastPending, &out.LastPending
+		*out = new(uint64)
+		**out = **in
+	}
 	if in.Metrics != nil {
 		in, out := &in.Metrics, &out.Metrics
 		*out = make(map[string]Metrics, len(*in))
@@ -1243,11 +1243,7 @@ func (in *StepSpec) DeepCopyInto(out *StepSpec) {
 		*out = new(Code)
 		**out = **in
 	}
-	if in.Scale != nil {
-		in, out := &in.Scale, &out.Scale
-		*out = new(Scale)
-		(*in).DeepCopyInto(*out)
-	}
+	out.Scale = in.Scale
 	if in.Sources != nil {
 		in, out := &in.Sources, &out.Sources
 		*out = make(Sources, len(*in))
diff --git a/config/ci.yaml b/config/ci.yaml
index 3002a037..7a8fdfe6 100644
--- a/config/ci.yaml
+++ b/config/ci.yaml
@@ -1186,18 +1186,25 @@ spec:
                         the default one is RestartPolicyAlways.
                       type: string
                     scale:
+                      default:
+                        desiredReplicas: ""
+                        peekDelay: defaultPeekDelay
+                        scalingDelay: defaultScalingDelay
                       properties:
-                        maxReplicas:
-                          format: int32
-                          type: integer
-                        minReplicas:
-                          format: int32
-                          type: integer
-                        replicaRatio:
-                          format: int32
-                          type: integer
-                      required:
-                      - minReplicas
+                        desiredReplicas:
+                          description: An expression to determine the number of replicas.
+                            Must evaluation to an `int`.
+                          type: string
+                        peekDelay:
+                          default: defaultPeekDelay
+                          description: An expression to determine the delay for peeking.
+                            Maybe string or duration, e.g. `"4m"`
+                          type: string
+                        scalingDelay:
+                          default: defaultScalingDelay
+                          description: An expression to determine the delay for scaling.
+                            Maybe string or duration, e.g. `"1m"`
+                          type: string
                       type: object
                     serviceAccountName:
                       default: pipeline
@@ -4806,18 +4813,25 @@ spec:
                   RestartPolicyAlways.
                 type: string
               scale:
+                default:
+                  desiredReplicas: ""
+                  peekDelay: defaultPeekDelay
+                  scalingDelay: defaultScalingDelay
                 properties:
-                  maxReplicas:
-                    format: int32
-                    type: integer
-                  minReplicas:
-                    format: int32
-                    type: integer
-                  replicaRatio:
-                    format: int32
-                    type: integer
-                required:
-                - minReplicas
+                  desiredReplicas:
+                    description: An expression to determine the number of replicas.
+                      Must evaluation to an `int`.
+                    type: string
+                  peekDelay:
+                    default: defaultPeekDelay
+                    description: An expression to determine the delay for peeking.
+                      Maybe string or duration, e.g. `"4m"`
+                    type: string
+                  scalingDelay:
+                    default: defaultScalingDelay
+                    description: An expression to determine the delay for scaling.
+                      Maybe string or duration, e.g. `"1m"`
+                    type: string
                 type: object
               serviceAccountName:
                 default: pipeline
@@ -7100,6 +7114,9 @@ spec:
               sinkStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
@@ -7128,6 +7145,9 @@ spec:
               sourceStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
diff --git a/config/crd/bases/dataflow.argoproj.io_pipelines.yaml b/config/crd/bases/dataflow.argoproj.io_pipelines.yaml
index b4386eb5..3883c691 100644
--- a/config/crd/bases/dataflow.argoproj.io_pipelines.yaml
+++ b/config/crd/bases/dataflow.argoproj.io_pipelines.yaml
@@ -1181,18 +1181,25 @@ spec:
                         the default one is RestartPolicyAlways.
                       type: string
                     scale:
+                      default:
+                        desiredReplicas: ""
+                        peekDelay: defaultPeekDelay
+                        scalingDelay: defaultScalingDelay
                       properties:
-                        maxReplicas:
-                          format: int32
-                          type: integer
-                        minReplicas:
-                          format: int32
-                          type: integer
-                        replicaRatio:
-                          format: int32
-                          type: integer
-                      required:
-                      - minReplicas
+                        desiredReplicas:
+                          description: An expression to determine the number of replicas.
+                            Must evaluation to an `int`.
+                          type: string
+                        peekDelay:
+                          default: defaultPeekDelay
+                          description: An expression to determine the delay for peeking.
+                            Maybe string or duration, e.g. `"4m"`
+                          type: string
+                        scalingDelay:
+                          default: defaultScalingDelay
+                          description: An expression to determine the delay for scaling.
+                            Maybe string or duration, e.g. `"1m"`
+                          type: string
                       type: object
                     serviceAccountName:
                       default: pipeline
diff --git a/config/crd/bases/dataflow.argoproj.io_steps.yaml b/config/crd/bases/dataflow.argoproj.io_steps.yaml
index 9fdb94d6..3deabc9d 100644
--- a/config/crd/bases/dataflow.argoproj.io_steps.yaml
+++ b/config/crd/bases/dataflow.argoproj.io_steps.yaml
@@ -1135,18 +1135,25 @@ spec:
                   RestartPolicyAlways.
                 type: string
               scale:
+                default:
+                  desiredReplicas: ""
+                  peekDelay: defaultPeekDelay
+                  scalingDelay: defaultScalingDelay
                 properties:
-                  maxReplicas:
-                    format: int32
-                    type: integer
-                  minReplicas:
-                    format: int32
-                    type: integer
-                  replicaRatio:
-                    format: int32
-                    type: integer
-                required:
-                - minReplicas
+                  desiredReplicas:
+                    description: An expression to determine the number of replicas.
+                      Must evaluation to an `int`.
+                    type: string
+                  peekDelay:
+                    default: defaultPeekDelay
+                    description: An expression to determine the delay for peeking.
+                      Maybe string or duration, e.g. `"4m"`
+                    type: string
+                  scalingDelay:
+                    default: defaultScalingDelay
+                    description: An expression to determine the delay for scaling.
+                      Maybe string or duration, e.g. `"1m"`
+                    type: string
                 type: object
               serviceAccountName:
                 default: pipeline
@@ -3429,6 +3436,9 @@ spec:
               sinkStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
@@ -3457,6 +3467,9 @@ spec:
               sourceStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
diff --git a/config/default.yaml b/config/default.yaml
index d72953aa..590cc914 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -1186,18 +1186,25 @@ spec:
                         the default one is RestartPolicyAlways.
                       type: string
                     scale:
+                      default:
+                        desiredReplicas: ""
+                        peekDelay: defaultPeekDelay
+                        scalingDelay: defaultScalingDelay
                       properties:
-                        maxReplicas:
-                          format: int32
-                          type: integer
-                        minReplicas:
-                          format: int32
-                          type: integer
-                        replicaRatio:
-                          format: int32
-                          type: integer
-                      required:
-                      - minReplicas
+                        desiredReplicas:
+                          description: An expression to determine the number of replicas.
+                            Must evaluation to an `int`.
+                          type: string
+                        peekDelay:
+                          default: defaultPeekDelay
+                          description: An expression to determine the delay for peeking.
+                            Maybe string or duration, e.g. `"4m"`
+                          type: string
+                        scalingDelay:
+                          default: defaultScalingDelay
+                          description: An expression to determine the delay for scaling.
+                            Maybe string or duration, e.g. `"1m"`
+                          type: string
                       type: object
                     serviceAccountName:
                       default: pipeline
@@ -4806,18 +4813,25 @@ spec:
                   RestartPolicyAlways.
                 type: string
               scale:
+                default:
+                  desiredReplicas: ""
+                  peekDelay: defaultPeekDelay
+                  scalingDelay: defaultScalingDelay
                 properties:
-                  maxReplicas:
-                    format: int32
-                    type: integer
-                  minReplicas:
-                    format: int32
-                    type: integer
-                  replicaRatio:
-                    format: int32
-                    type: integer
-                required:
-                - minReplicas
+                  desiredReplicas:
+                    description: An expression to determine the number of replicas.
+                      Must evaluation to an `int`.
+                    type: string
+                  peekDelay:
+                    default: defaultPeekDelay
+                    description: An expression to determine the delay for peeking.
+                      Maybe string or duration, e.g. `"4m"`
+                    type: string
+                  scalingDelay:
+                    default: defaultScalingDelay
+                    description: An expression to determine the delay for scaling.
+                      Maybe string or duration, e.g. `"1m"`
+                    type: string
                 type: object
               serviceAccountName:
                 default: pipeline
@@ -7100,6 +7114,9 @@ spec:
               sinkStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
@@ -7128,6 +7145,9 @@ spec:
               sourceStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
diff --git a/config/dev.yaml b/config/dev.yaml
index 1d3ac005..de77692a 100644
--- a/config/dev.yaml
+++ b/config/dev.yaml
@@ -1186,18 +1186,25 @@ spec:
                         the default one is RestartPolicyAlways.
                       type: string
                     scale:
+                      default:
+                        desiredReplicas: ""
+                        peekDelay: defaultPeekDelay
+                        scalingDelay: defaultScalingDelay
                       properties:
-                        maxReplicas:
-                          format: int32
-                          type: integer
-                        minReplicas:
-                          format: int32
-                          type: integer
-                        replicaRatio:
-                          format: int32
-                          type: integer
-                      required:
-                      - minReplicas
+                        desiredReplicas:
+                          description: An expression to determine the number of replicas.
+                            Must evaluation to an `int`.
+                          type: string
+                        peekDelay:
+                          default: defaultPeekDelay
+                          description: An expression to determine the delay for peeking.
+                            Maybe string or duration, e.g. `"4m"`
+                          type: string
+                        scalingDelay:
+                          default: defaultScalingDelay
+                          description: An expression to determine the delay for scaling.
+                            Maybe string or duration, e.g. `"1m"`
+                          type: string
                       type: object
                     serviceAccountName:
                       default: pipeline
@@ -4806,18 +4813,25 @@ spec:
                   RestartPolicyAlways.
                 type: string
               scale:
+                default:
+                  desiredReplicas: ""
+                  peekDelay: defaultPeekDelay
+                  scalingDelay: defaultScalingDelay
                 properties:
-                  maxReplicas:
-                    format: int32
-                    type: integer
-                  minReplicas:
-                    format: int32
-                    type: integer
-                  replicaRatio:
-                    format: int32
-                    type: integer
-                required:
-                - minReplicas
+                  desiredReplicas:
+                    description: An expression to determine the number of replicas.
+                      Must evaluation to an `int`.
+                    type: string
+                  peekDelay:
+                    default: defaultPeekDelay
+                    description: An expression to determine the delay for peeking.
+                      Maybe string or duration, e.g. `"4m"`
+                    type: string
+                  scalingDelay:
+                    default: defaultScalingDelay
+                    description: An expression to determine the delay for scaling.
+                      Maybe string or duration, e.g. `"1m"`
+                    type: string
                 type: object
               serviceAccountName:
                 default: pipeline
@@ -7100,6 +7114,9 @@ spec:
               sinkStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
@@ -7128,6 +7145,9 @@ spec:
               sourceStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
diff --git a/config/quick-start.yaml b/config/quick-start.yaml
index d72953aa..590cc914 100644
--- a/config/quick-start.yaml
+++ b/config/quick-start.yaml
@@ -1186,18 +1186,25 @@ spec:
                         the default one is RestartPolicyAlways.
                       type: string
                     scale:
+                      default:
+                        desiredReplicas: ""
+                        peekDelay: defaultPeekDelay
+                        scalingDelay: defaultScalingDelay
                       properties:
-                        maxReplicas:
-                          format: int32
-                          type: integer
-                        minReplicas:
-                          format: int32
-                          type: integer
-                        replicaRatio:
-                          format: int32
-                          type: integer
-                      required:
-                      - minReplicas
+                        desiredReplicas:
+                          description: An expression to determine the number of replicas.
+                            Must evaluation to an `int`.
+                          type: string
+                        peekDelay:
+                          default: defaultPeekDelay
+                          description: An expression to determine the delay for peeking.
+                            Maybe string or duration, e.g. `"4m"`
+                          type: string
+                        scalingDelay:
+                          default: defaultScalingDelay
+                          description: An expression to determine the delay for scaling.
+                            Maybe string or duration, e.g. `"1m"`
+                          type: string
                       type: object
                     serviceAccountName:
                       default: pipeline
@@ -4806,18 +4813,25 @@ spec:
                   RestartPolicyAlways.
                 type: string
               scale:
+                default:
+                  desiredReplicas: ""
+                  peekDelay: defaultPeekDelay
+                  scalingDelay: defaultScalingDelay
                 properties:
-                  maxReplicas:
-                    format: int32
-                    type: integer
-                  minReplicas:
-                    format: int32
-                    type: integer
-                  replicaRatio:
-                    format: int32
-                    type: integer
-                required:
-                - minReplicas
+                  desiredReplicas:
+                    description: An expression to determine the number of replicas.
+                      Must evaluation to an `int`.
+                    type: string
+                  peekDelay:
+                    default: defaultPeekDelay
+                    description: An expression to determine the delay for peeking.
+                      Maybe string or duration, e.g. `"4m"`
+                    type: string
+                  scalingDelay:
+                    default: defaultScalingDelay
+                    description: An expression to determine the delay for scaling.
+                      Maybe string or duration, e.g. `"1m"`
+                    type: string
                 type: object
               serviceAccountName:
                 default: pipeline
@@ -7100,6 +7114,9 @@ spec:
               sinkStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
@@ -7128,6 +7145,9 @@ spec:
               sourceStatuses:
                 additionalProperties:
                   properties:
+                    lastPending:
+                      format: int64
+                      type: integer
                     metrics:
                       additionalProperties:
                         properties:
diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md
index 742d06de..f26c4c75 100644
--- a/docs/EXAMPLES.md
+++ b/docs/EXAMPLES.md
@@ -60,31 +60,22 @@ kubectl apply -f https://raw.githubusercontent.com/argoproj-labs/argo-dataflow/m
 
 This is an example of having multiple replicas for a single step.
 
-Replicas are automatically scaled up and down depending on the number of messages pending processing.
+Replicas are automatically scaled up and down depending on the the desired formula, which can be computed using the following:
 
-The ratio is defined as the number of pending messages per replica:
+* `P` total number of pending messages.
+* `p` change in number of pending messages
+* `c` the current number of replicas.
+* `minmax(v, min, max)` a function to constraint the minimum and maximum number of replicas.
 
-```
-replicas = pending / ratio
-```
-
-The number of replicas will not scale beyond the min/max bounds (except when *peeking*, see below):
-
-```
-min <= replicas <= max
-```
+In this example:
 
-* `min` is used as the initial number of replicas.
-* If `ratio` is undefined no scaling can occur; `max` is meaningless.
-* If `ratio` is defined but `max` is not, the step may scale to infinity.
-* If `max` and `ratio` are undefined, then the number of replicas is `min`.
-* In this example, because the ratio is 1000, if 2000 messages pending, two replicas will be started.
-* To prevent scaling up and down repeatedly - scale up or down occurs a maximum of once a minute.
-* The same message will not be send to two different replicas.
+* Aa period is 60s
+* Each replica can consume 250 messages each second
+* We want to consume all pending messages in 10 periods. 
 
 ### Scale-To-Zero and Peeking
 
-You can scale to zero by setting `minReplicas: 0`. The number of replicas will start at zero, and periodically be scaled
+You can scale to zero. The number of replicas will be periodically scaled
 to 1  so it can "peek" the the message queue. The number of pending messages is measured and the target number
 of replicas re-calculated.
 
diff --git a/docs/FEATURES.md b/docs/FEATURES.md
index a200b4ab..8a7ce3b3 100644
--- a/docs/FEATURES.md
+++ b/docs/FEATURES.md
@@ -18,6 +18,7 @@ alpha/beta/stable.
 | Cron source | v0.0.59 | |
 | Dedupe step | v0.0.59 | || |
 | Expand step | v0.0.59 | v0.0.70 | |
+| Expression based scaling | v0.0.90 | | |
 | Filter step | v0.0.59 | v0.0.70 | |
 | FMEA tests | | v0.0.59 | |
 | [Generator step](STEPS.md#Generator-step) | v0.0.59 | | |
diff --git a/docs/SCALING.md b/docs/SCALING.md
index dda92bbb..c4a90afe 100644
--- a/docs/SCALING.md
+++ b/docs/SCALING.md
@@ -6,5 +6,4 @@ You can scale in the following ways:
 * Using `kubect scale step/{pipelineName}-{stepName}` --replicas 1
 * Using a [Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/).
 
-Not all sources or steps types will scale linearly. Some cannot be scaled (cron source, de-dupe step).
-See [examples](EXAMPLES.md).
\ No newline at end of file
+Not all sources or steps types will scale linearly. Some cannot be scaled. See [examples](EXAMPLES.md).
\ No newline at end of file
diff --git a/dsls/python/argo_dataflow/pipeline.py b/dsls/python/argo_dataflow/pipeline.py
index 3da1c4b2..83a1bb11 100644
--- a/dsls/python/argo_dataflow/pipeline.py
+++ b/dsls/python/argo_dataflow/pipeline.py
@@ -179,7 +179,7 @@ def __init__(self, name, sources=[], volumes=[], terminator=False, sidecarResour
         self._name = name
         self._sources = sources
         self._sinks = []
-        self._scale = {}
+        self._scale = None
         self._volumes = volumes
         self._terminator = terminator
         self._annotations = []
@@ -197,11 +197,9 @@ def kafka(self, subject, name=None, a_sync=False):
         self._sinks.append(KafkaSink(subject, name=name, a_sync=a_sync))
         return self
 
-    def scale(self, minReplicas, maxReplicas, replicaRatio):
+    def scale(self, desiredReplicas):
         self._scale = {
-            'minReplicas': minReplicas,
-            'maxReplicas': maxReplicas,
-            'replicaRatio': replicaRatio
+            'desiredReplicas': desiredReplicas,
         }
         return self
 
@@ -229,7 +227,7 @@ def dump(self):
             y['sources'] = [x.dump() for x in self._sources]
         if len(self._sinks):
             y['sinks'] = [x.dump() for x in self._sinks]
-        if len(self._scale) > 0:
+        if self._scale:
             y['scale'] = self._scale
         if len(self._volumes) > 0:
             y['volumes'] = self._volumes
diff --git a/examples/103-autoscaling-pipeline.py b/examples/103-autoscaling-pipeline.py
index 2204d335..0ccfc9da 100644
--- a/examples/103-autoscaling-pipeline.py
+++ b/examples/103-autoscaling-pipeline.py
@@ -5,37 +5,28 @@
      .owner('argoproj-labs')
      .describe("""This is an example of having multiple replicas for a single step.
 
-Replicas are automatically scaled up and down depending on the number of messages pending processing.
+Replicas are automatically scaled up and down depending on the the desired formula, which can be computed using the following:
 
-The ratio is defined as the number of pending messages per replica:
+* `P` total number of pending messages.
+* `p` change in number of pending messages
+* `c` the current number of replicas.
+* `minmax(v, min, max)` a function to constraint the minimum and maximum number of replicas.
 
-```
-replicas = pending / ratio
-```
+In this example:
 
-The number of replicas will not scale beyond the min/max bounds (except when *peeking*, see below):
-
-```
-min <= replicas <= max
-```
-
-* `min` is used as the initial number of replicas.
-* If `ratio` is undefined no scaling can occur; `max` is meaningless.
-* If `ratio` is defined but `max` is not, the step may scale to infinity.
-* If `max` and `ratio` are undefined, then the number of replicas is `min`.
-* In this example, because the ratio is 1000, if 2000 messages pending, two replicas will be started.
-* To prevent scaling up and down repeatedly - scale up or down occurs a maximum of once a minute.
-* The same message will not be send to two different replicas.
+* Aa period is 60s
+* Each replica can consume 250 messages each second
+* We want to consume all pending messages in 10 periods. 
 
 ### Scale-To-Zero and Peeking
 
-You can scale to zero by setting `minReplicas: 0`. The number of replicas will start at zero, and periodically be scaled
+You can scale to zero. The number of replicas will be periodically scaled
 to 1  so it can "peek" the the message queue. The number of pending messages is measured and the target number
 of replicas re-calculated.""")
      .step(
         (kafka('input-topic')
          .cat('main')
-         .scale(0, 4, 1000)
+         .scale('minmax(c + p / 60 / 250 + P / (10 * 60 * 250), 0, 4)')
          .kafka('output-topic'))
     )
      .save())
diff --git a/examples/103-autoscaling-pipeline.yaml b/examples/103-autoscaling-pipeline.yaml
index 643ba17a..56b6a9c9 100644
--- a/examples/103-autoscaling-pipeline.yaml
+++ b/examples/103-autoscaling-pipeline.yaml
@@ -2,36 +2,17 @@ apiVersion: dataflow.argoproj.io/v1alpha1
 kind: Pipeline
 metadata:
   annotations:
-    dataflow.argoproj.io/description: |-
-      This is an example of having multiple replicas for a single step.
-
-      Replicas are automatically scaled up and down depending on the number of messages pending processing.
-
-      The ratio is defined as the number of pending messages per replica:
-
-      ```
-      replicas = pending / ratio
-      ```
-
-      The number of replicas will not scale beyond the min/max bounds (except when *peeking*, see below):
-
-      ```
-      min <= replicas <= max
-      ```
-
-      * `min` is used as the initial number of replicas.
-      * If `ratio` is undefined no scaling can occur; `max` is meaningless.
-      * If `ratio` is defined but `max` is not, the step may scale to infinity.
-      * If `max` and `ratio` are undefined, then the number of replicas is `min`.
-      * In this example, because the ratio is 1000, if 2000 messages pending, two replicas will be started.
-      * To prevent scaling up and down repeatedly - scale up or down occurs a maximum of once a minute.
-      * The same message will not be send to two different replicas.
-
-      ### Scale-To-Zero and Peeking
-
-      You can scale to zero by setting `minReplicas: 0`. The number of replicas will start at zero, and periodically be scaled
-      to 1  so it can "peek" the the message queue. The number of pending messages is measured and the target number
-      of replicas re-calculated.
+    dataflow.argoproj.io/description: "This is an example of having multiple replicas\
+      \ for a single step.\n\nReplicas are automatically scaled up and down depending\
+      \ on the the desired formula, which can be computed using the following:\n\n\
+      * `P` total number of pending messages.\n* `p` change in number of pending messages\n\
+      * `c` the current number of replicas.\n* `minmax(v, min, max)` a function to\
+      \ constraint the minimum and maximum number of replicas.\n\nIn this example:\n\
+      \n* Aa period is 60s\n* Each replica can consume 250 messages each second\n\
+      * We want to consume all pending messages in 10 periods. \n\n### Scale-To-Zero\
+      \ and Peeking\n\nYou can scale to zero. The number of replicas will be periodically\
+      \ scaled\nto 1  so it can \"peek\" the the message queue. The number of pending\
+      \ messages is measured and the target number\nof replicas re-calculated."
     dataflow.argoproj.io/owner: argoproj-labs
   name: 103-autoscaling
 spec:
@@ -39,9 +20,7 @@ spec:
   - cat: {}
     name: main
     scale:
-      maxReplicas: 4
-      minReplicas: 0
-      replicaRatio: 1000
+      desiredReplicas: minmax(c + p / 60 / 250 + P / (10 * 60 * 250), 0, 4)
     sinks:
     - kafka:
         topic: output-topic
diff --git a/examples/201-word-count-pipeline.py b/examples/201-word-count-pipeline.py
index 499f9927..532967cb 100644
--- a/examples/201-word-count-pipeline.py
+++ b/examples/201-word-count-pipeline.py
@@ -30,7 +30,7 @@
                     image='ubuntu:latest',
                     fifo=True,
                     )
-         .scale(0, 1, 1)
+         .scale('minmax(pending, 0, 1)')
          .stan('words')
          ))
      .step(
diff --git a/examples/201-word-count-pipeline.yaml b/examples/201-word-count-pipeline.yaml
index 834378bc..f4db0277 100644
--- a/examples/201-word-count-pipeline.yaml
+++ b/examples/201-word-count-pipeline.yaml
@@ -48,9 +48,7 @@ spec:
         fifo: true
     name: split-lines
     scale:
-      maxReplicas: 1
-      minReplicas: 0
-      replicaRatio: 1
+      desiredReplicas: minmax(pending, 0, 1)
     sinks:
     - stan:
         subject: words
diff --git a/manager/controllers/config.go b/manager/controllers/config.go
index 56e59baa..67d67f28 100644
--- a/manager/controllers/config.go
+++ b/manager/controllers/config.go
@@ -12,14 +12,11 @@ import (
 )
 
 var (
-	scalingDelay   = util.GetEnvDuration(dfv1.EnvScalingDelay, time.Minute)
-	peekDelay      = util.GetEnvDuration(dfv1.EnvPeekDelay, 4*time.Minute)
-	imagePrefix    = os.Getenv(dfv1.EnvImagePrefix)
-	imageFormat    = ""
-	runnerImage    = ""
-	pullPolicy     = corev1.PullPolicy(os.Getenv(dfv1.EnvPullPolicy))
-	updateInterval = util.GetEnvDuration(dfv1.EnvUpdateInterval, 1*time.Minute)
-
+	imagePrefix      = os.Getenv(dfv1.EnvImagePrefix)
+	imageFormat      = ""
+	runnerImage      = ""
+	pullPolicy       = corev1.PullPolicy(os.Getenv(dfv1.EnvPullPolicy))
+	updateInterval   = util.GetEnvDuration(dfv1.EnvUpdateInterval, 1*time.Minute)
 	logger           = util.NewLogger()
 	imagePullSecrets = util.GetEnvStringArr(dfv1.EnvImagePullSecrets, []string{})
 )
@@ -39,8 +36,6 @@ func init() {
 		"runnerImage", runnerImage,
 		"pullPolicy", pullPolicy,
 		"updateInterval", updateInterval.String(),
-		"scalingDelay", scalingDelay.String(),
-		"peekDelay", peekDelay.String(),
 		"imagePullSecrets", imagePullSecrets,
 	)
 }
diff --git a/manager/controllers/scaling/funcs.go b/manager/controllers/scaling/funcs.go
new file mode 100644
index 00000000..cb434e17
--- /dev/null
+++ b/manager/controllers/scaling/funcs.go
@@ -0,0 +1,11 @@
+package scaling
+
+func minmax(v, min, max int) int {
+	if v < min {
+		return min
+	} else if v > max {
+		return max
+	} else {
+		return v
+	}
+}
diff --git a/manager/controllers/scaling/scaling.go b/manager/controllers/scaling/scaling.go
new file mode 100644
index 00000000..b1e29061
--- /dev/null
+++ b/manager/controllers/scaling/scaling.go
@@ -0,0 +1,106 @@
+package scaling
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/antonmedv/expr"
+	dfv1 "github.com/argoproj-labs/argo-dataflow/api/v1alpha1"
+	sharedutil "github.com/argoproj-labs/argo-dataflow/shared/util"
+)
+
+var (
+	logger              = sharedutil.NewLogger()
+	defaultScalingDelay = sharedutil.GetEnvDuration(dfv1.EnvScalingDelay, time.Minute)
+	defaultPeekDelay    = sharedutil.GetEnvDuration(dfv1.EnvPeekDelay, 4*time.Minute)
+)
+
+func init() {
+	logger.Info("scaling config",
+		"defaultScalingDelay", defaultScalingDelay.String(),
+		"defaultPeekDelay", defaultPeekDelay.String(),
+	)
+}
+
+func GetDesiredReplicas(step dfv1.Step) (int, error) {
+	currentReplicas := int(step.Status.Replicas)
+	lastScaledAt := time.Since(step.Status.LastScaledAt.Time)
+	scale := step.Spec.Scale
+	var scalingDelay time.Duration
+	var peekDelay time.Duration
+	desiredReplicas := currentReplicas
+	{
+
+		var err error
+		if scalingDelay, err = evalAsDuration(scale.ScalingDelay, map[string]interface{}{
+			"defaultScalingDelay": defaultScalingDelay,
+		}); err != nil {
+			return 0, fmt.Errorf("failed to evaluate %q: %w", scale.ScalingDelay, err)
+		}
+		if peekDelay, err = evalAsDuration(scale.PeekDelay, map[string]interface{}{
+			"defaultPeekDelay": defaultPeekDelay,
+		}); err != nil {
+			return 0, fmt.Errorf("failed to evaluate %q: %w", scale.PeekDelay, err)
+		}
+		if scale.DesiredReplicas != "" {
+			pending := step.Status.SourceStatuses.GetPending()
+			c := int(step.Status.Replicas)
+			P := int(pending)
+			p := int(pending - step.Status.SourceStatuses.GetLastPending())
+			r, err := expr.Eval(scale.DesiredReplicas, map[string]interface{}{"c": c, "P": P, "p": p, "minmax": minmax})
+			if err != nil {
+				return 0, err
+			}
+			var ok bool
+			desiredReplicas, ok = r.(int)
+			if !ok {
+				return 0, fmt.Errorf("failed to evaluate %q as int, got %T", scale.DesiredReplicas, r)
+			}
+			logger.Info("desired replicas", "c", c, "P", P, "p", p, "d", desiredReplicas, "scalingDelay", scalingDelay, "peekDelay", peekDelay)
+		}
+	}
+	if lastScaledAt < scalingDelay {
+		return currentReplicas, nil
+	}
+	// do we need to peek? currentReplicas and desiredReplicas must both be zero
+	if currentReplicas <= 0 && desiredReplicas == 0 && lastScaledAt > peekDelay {
+		return 1, nil
+	}
+	// prevent violent scale-up and scale-down by only scaling by 1 each time
+	if desiredReplicas > currentReplicas {
+		return currentReplicas + 1, nil
+	} else if desiredReplicas < currentReplicas {
+		return currentReplicas - 1, nil
+	} else {
+		return desiredReplicas, nil
+	}
+}
+
+func evalAsDuration(input string, env map[string]interface{}) (time.Duration, error) {
+	if r, err := expr.Eval(input, env); err != nil {
+		return 0, err
+	} else {
+		switch v := r.(type) {
+		case string:
+			return time.ParseDuration(v)
+		case time.Duration:
+			return v, nil
+		default:
+			return 0, fmt.Errorf("wanted string, got to %T", r)
+		}
+	}
+}
+
+func RequeueAfter(step dfv1.Step, currentReplicas, desiredReplicas int) (time.Duration, error) {
+	if currentReplicas <= 0 && desiredReplicas == 0 {
+		scale := step.Spec.Scale
+		if scalingDelay, err := evalAsDuration(scale.ScalingDelay, map[string]interface{}{
+			"defaultScalingDelay": defaultScalingDelay,
+		}); err != nil {
+			return 0, fmt.Errorf("failed to evaluate %q: %w", scale.ScalingDelay, err)
+		} else {
+			return scalingDelay, nil
+		}
+	}
+	return 0, nil
+}
diff --git a/manager/controllers/step_controller.go b/manager/controllers/step_controller.go
index f0668150..b1231cbe 100644
--- a/manager/controllers/step_controller.go
+++ b/manager/controllers/step_controller.go
@@ -23,6 +23,8 @@ import (
 	"strconv"
 	"time"
 
+	"github.com/argoproj-labs/argo-dataflow/manager/controllers/scaling"
+
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/client-go/dynamic"
 
@@ -90,9 +92,11 @@ func (r *StepReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
 
 	log.Info("reconciling")
 
-	if step.Spec.Scale != nil {
-		desiredReplicas := step.GetTargetReplicas(scalingDelay, peekDelay)
-
+	if step.Spec.Scale.DesiredReplicas != "" {
+		desiredReplicas, err := scaling.GetDesiredReplicas(*step)
+		if err != nil {
+			return ctrl.Result{}, err
+		}
 		if int(step.Spec.Replicas) != desiredReplicas {
 			log.Info("auto-scaling step", "currentReplicas", step.Spec.Replicas, "desiredReplicas", desiredReplicas)
 			if _, err := r.DynamicInterface.
@@ -295,9 +299,14 @@ func (r *StepReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
 		}
 	}
 
-	return ctrl.Result{
-		RequeueAfter: dfv1.RequeueAfter(currentReplicas, desiredReplicas, scalingDelay),
-	}, nil
+	requeueAfter, err := scaling.RequeueAfter(*step, currentReplicas, desiredReplicas)
+	if err != nil {
+		return ctrl.Result{}, err
+	}
+	if requeueAfter > 0 {
+		log.Info("requeue", "requeueAfter", requeueAfter.String())
+	}
+	return ctrl.Result{RequeueAfter: requeueAfter}, nil
 }
 
 func eventReason(currentReplicas, desiredReplicas int) string {
diff --git a/runner/sidecar/sidecar.go b/runner/sidecar/sidecar.go
index 474541ed..42258718 100644
--- a/runner/sidecar/sidecar.go
+++ b/runner/sidecar/sidecar.go
@@ -10,8 +10,6 @@ import (
 	"sync"
 	"time"
 
-	runtimeutil "k8s.io/apimachinery/pkg/util/runtime"
-
 	dfv1 "github.com/argoproj-labs/argo-dataflow/api/v1alpha1"
 	sharedutil "github.com/argoproj-labs/argo-dataflow/shared/util"
 	"github.com/prometheus/client_golang/prometheus"
@@ -21,6 +19,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
+	runtimeutil "k8s.io/apimachinery/pkg/util/runtime"
 	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/dynamic"
 	"k8s.io/client-go/kubernetes"
@@ -243,22 +242,17 @@ func patchStepStatus() {
 					}
 					// the step with change while this goroutine is running, so we must copy the data for this
 					// replica back to the status
-					r := strconv.Itoa(replica)
 					for name, s := range step.Status.SourceStatuses {
 						if v.Status.SourceStatuses[name].Metrics == nil {
-							x := v.Status.SourceStatuses[name]
-							x.Metrics = map[string]dfv1.Metrics{}
-							v.Status.SourceStatuses[name] = x
+							s.Metrics = map[string]dfv1.Metrics{}
 						}
-						v.Status.SourceStatuses[name].Metrics[r] = s.Metrics[r]
+						v.Status.SourceStatuses[name] = s
 					}
 					for name, s := range step.Status.SinkStatues {
 						if v.Status.SinkStatues[name].Metrics == nil {
-							x := v.Status.SinkStatues[name]
-							x.Metrics = map[string]dfv1.Metrics{}
-							v.Status.SinkStatues[name] = x
+							s.Metrics = map[string]dfv1.Metrics{}
 						}
-						v.Status.SinkStatues[name].Metrics[r] = s.Metrics[r]
+						v.Status.SinkStatues[name] = s
 					}
 					step = v
 				})


Test patch:
diff --git a/api/v1alpha1/scale_test.go b/api/v1alpha1/scale_test.go
deleted file mode 100644
index 644c6bb9..00000000
--- a/api/v1alpha1/scale_test.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package v1alpha1
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestScale_Calculate(t *testing.T) {
-	assert.Equal(t, 0, Scale{MinReplicas: 0}.Calculate(0))
-	assert.Equal(t, 0, Scale{MinReplicas: 0}.Calculate(0))
-	max := uint32(0)
-	assert.Equal(t, 0, Scale{MinReplicas: 1, MaxReplicas: &max}.Calculate(0))
-	assert.Equal(t, 2, Scale{MinReplicas: 1, ReplicaRatio: 2}.Calculate(4))
-	max = uint32(1)
-	assert.Equal(t, 1, Scale{MinReplicas: 1, MaxReplicas: &max, ReplicaRatio: 2}.Calculate(4))
-}
diff --git a/api/v1alpha1/source_statuses_test.go b/api/v1alpha1/source_statuses_test.go
index 6d19050a..8931d939 100644
--- a/api/v1alpha1/source_statuses_test.go
+++ b/api/v1alpha1/source_statuses_test.go
@@ -72,12 +72,14 @@ func TestSourceStatuses_SetPending(t *testing.T) {
 	ss.SetPending("bar", 34)
 
 	if assert.Len(t, ss, 1) {
+		assert.Equal(t, uint64(23), *ss["bar"].LastPending)
 		assert.Equal(t, uint64(34), *ss["bar"].Pending)
 	}
 
 	ss.SetPending("bar", 45)
 
 	if assert.Len(t, ss, 1) {
+		assert.Equal(t, uint64(34), *ss["bar"].LastPending)
 		assert.Equal(t, uint64(45), *ss["bar"].Pending)
 	}
 }
@@ -88,6 +90,12 @@ func TestSourceStatus_GetPending(t *testing.T) {
 	assert.Equal(t, uint64(1), SourceStatuses{"0": {Pending: &v}}.GetPending())
 }
 
+func TestSourceStatus_GetLastPending(t *testing.T) {
+	assert.Equal(t, uint64(0), SourceStatuses{}.GetLastPending())
+	v := uint64(1)
+	assert.Equal(t, uint64(1), SourceStatuses{"0": {LastPending: &v}}.GetLastPending())
+}
+
 func TestSourceStatuses_IncrRetries(t *testing.T) {
 	sources := SourceStatuses{}
 	sources.IncrRetries("one", 1)
diff --git a/api/v1alpha1/step_types_test.go b/api/v1alpha1/step_types_test.go
index 2ca65ba5..5a47030d 100644
--- a/api/v1alpha1/step_types_test.go
+++ b/api/v1alpha1/step_types_test.go
@@ -10,7 +10,6 @@ import (
 	"k8s.io/utils/pointer"
 
 	"github.com/stretchr/testify/assert"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 func TestStep_GetPodSpec(t *testing.T) {
@@ -20,7 +19,7 @@ func TestStep_GetPodSpec(t *testing.T) {
 		{Name: "ARGO_DATAFLOW_NAMESPACE", Value: "my-ns"},
 		{Name: "ARGO_DATAFLOW_PIPELINE_NAME", Value: "my-pl"},
 		{Name: "ARGO_DATAFLOW_REPLICA", Value: "1"},
-		{Name: "ARGO_DATAFLOW_STEP", Value: `{"metadata":{"creationTimestamp":null},"spec":{"name":"main","cat":{},"sidecar":{"resources":{}}},"status":{"phase":"","replicas":0,"lastScaledAt":null}}`},
+		{Name: "ARGO_DATAFLOW_STEP", Value: `{"metadata":{"creationTimestamp":null},"spec":{"name":"main","cat":{},"scale":{},"sidecar":{"resources":{}}},"status":{"phase":"","replicas":0,"lastScaledAt":null}}`},
 		{Name: "ARGO_DATAFLOW_UPDATE_INTERVAL", Value: "1m0s"},
 		{Name: "GODEBUG"},
 	}
@@ -142,77 +141,3 @@ func TestStep_GetPodSpec(t *testing.T) {
 		})
 	}
 }
-
-func TestStep_GetTargetReplicas(t *testing.T) {
-	old := metav1.Time{}
-	recent := metav1.Time{Time: time.Now().Add(-2 * time.Minute)}
-	now := metav1.Time{Time: time.Now()}
-	scalingDelay := time.Minute
-	peekDelay := 4 * time.Minute
-	t.Run("Init", func(t *testing.T) {
-		t.Run("Min=0", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{MinReplicas: 0}}}
-			assert.Equal(t, 1, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=1", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{MinReplicas: 1}}}
-			assert.Equal(t, 1, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-	})
-	t.Run("ScalingUp", func(t *testing.T) {
-		t.Run("Min=2,Replicas=1,LastScaledAt=old", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{MinReplicas: 2}}, Status: StepStatus{LastScaledAt: old, Replicas: 1}}
-			assert.Equal(t, 2, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=2,Replicas=1,LastScaledAt=recent", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{MinReplicas: 2}}, Status: StepStatus{LastScaledAt: recent, Replicas: 1}}
-			assert.Equal(t, 2, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=2,Replicas=1,LastScaledAt=now", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{MinReplicas: 2}}, Status: StepStatus{LastScaledAt: now, Replicas: 1}}
-			assert.Equal(t, 1, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-	})
-	t.Run("ScalingDown", func(t *testing.T) {
-		t.Run("Min=1,Replicas=2,LastScaledAt=old", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{MinReplicas: 1}}, Status: StepStatus{LastScaledAt: old, Replicas: 2}}
-			assert.Equal(t, 1, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=1,Replicas=2,LastScaledAt=recent", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{MinReplicas: 1}}, Status: StepStatus{LastScaledAt: recent, Replicas: 2}}
-			assert.Equal(t, 1, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=1,Replicas=2,LastScaledAt=now", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{MinReplicas: 1}}, Status: StepStatus{LastScaledAt: now, Replicas: 2}}
-			assert.Equal(t, 2, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-	})
-	t.Run("ScaleToZero", func(t *testing.T) {
-		t.Run("Min=0,Replicas=1,LastScaledAt=old", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{}}, Status: StepStatus{LastScaledAt: old, Replicas: 1}}
-			assert.Equal(t, 0, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=0,Replicas=1,LastScaledAt=recent", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{}}, Status: StepStatus{LastScaledAt: recent, Replicas: 1}}
-			assert.Equal(t, 0, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=0,Replicas=1,LastScaledAt=now", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{}}, Status: StepStatus{LastScaledAt: now, Replicas: 1}}
-			assert.Equal(t, 1, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-	})
-	t.Run("Peek", func(t *testing.T) {
-		t.Run("Min=0,Replicas=0,LastScaledAt=old", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{}}, Status: StepStatus{LastScaledAt: old}}
-			assert.Equal(t, 1, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=0,Replicas=0,LastScaledAt=recent", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{}}, Status: StepStatus{LastScaledAt: now}}
-			assert.Equal(t, 0, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-		t.Run("Min=0,Replicas=0,LastScaledAt=now", func(t *testing.T) {
-			s := &Step{Spec: StepSpec{Scale: &Scale{}}, Status: StepStatus{LastScaledAt: now}}
-			assert.Equal(t, 0, s.GetTargetReplicas(scalingDelay, peekDelay))
-		})
-	})
-}
diff --git a/manager/controllers/scaling/scaling_test.go b/manager/controllers/scaling/scaling_test.go
new file mode 100644
index 00000000..2dc3db90
--- /dev/null
+++ b/manager/controllers/scaling/scaling_test.go
@@ -0,0 +1,124 @@
+package scaling
+
+import (
+	"testing"
+	"time"
+
+	dfv1 "github.com/argoproj-labs/argo-dataflow/api/v1alpha1"
+	"github.com/stretchr/testify/assert"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestGetDesiredReplicas(t *testing.T) {
+	t.Run("Peek", func(t *testing.T) {
+		step := dfv1.Step{
+			Spec: dfv1.StepSpec{
+				Scale: dfv1.Scale{
+					PeekDelay:    `defaultPeekDelay`,
+					ScalingDelay: "defaultScalingDelay",
+				},
+			},
+		}
+		replicas, err := GetDesiredReplicas(step)
+		assert.NoError(t, err)
+		assert.Equal(t, 1, replicas)
+	})
+	t.Run("TooRecentToChange", func(t *testing.T) {
+		step := dfv1.Step{
+			Spec: dfv1.StepSpec{
+				Scale: dfv1.Scale{
+					PeekDelay:       `defaultPeekDelay`,
+					ScalingDelay:    "defaultScalingDelay",
+					DesiredReplicas: "1",
+				},
+			},
+			Status: dfv1.StepStatus{LastScaledAt: metav1.Now()},
+		}
+		replicas, err := GetDesiredReplicas(step)
+		assert.NoError(t, err)
+		assert.Equal(t, 0, replicas)
+	})
+	t.Run("ScaleUpOnlyOne", func(t *testing.T) {
+		step := dfv1.Step{
+			Spec: dfv1.StepSpec{
+				Scale: dfv1.Scale{
+					PeekDelay:       `defaultPeekDelay`,
+					ScalingDelay:    "defaultScalingDelay",
+					DesiredReplicas: "2",
+				},
+			},
+		}
+		replicas, err := GetDesiredReplicas(step)
+		assert.NoError(t, err)
+		assert.Equal(t, 1, replicas)
+	})
+	t.Run("ScaleDownOnlyOne", func(t *testing.T) {
+		step := dfv1.Step{
+			Spec: dfv1.StepSpec{
+				Scale: dfv1.Scale{
+					PeekDelay:       `defaultPeekDelay`,
+					ScalingDelay:    "defaultScalingDelay",
+					DesiredReplicas: "0",
+				},
+			},
+			Status: dfv1.StepStatus{Replicas: 2},
+		}
+		replicas, err := GetDesiredReplicas(step)
+		assert.NoError(t, err)
+		assert.Equal(t, 1, replicas)
+	})
+	t.Run("ScaleUnchanged", func(t *testing.T) {
+		step := dfv1.Step{
+			Spec: dfv1.StepSpec{
+				Scale: dfv1.Scale{
+					PeekDelay:       `defaultPeekDelay`,
+					ScalingDelay:    "defaultScalingDelay",
+					DesiredReplicas: "1",
+				},
+			},
+			Status: dfv1.StepStatus{Replicas: 1},
+		}
+		replicas, err := GetDesiredReplicas(step)
+		assert.NoError(t, err)
+		assert.Equal(t, 1, replicas)
+	})
+
+	t.Run("PeekDelayAndScalingDelayAsStringIsValid", func(t *testing.T) {
+		step := dfv1.Step{
+			Spec: dfv1.StepSpec{
+				Scale: dfv1.Scale{
+					PeekDelay:    `"1m"`,
+					ScalingDelay: `"2m"`,
+				},
+			},
+		}
+		_, err := GetDesiredReplicas(step)
+		assert.NoError(t, err)
+	})
+}
+
+func TestRequeueAfter(t *testing.T) {
+	t.Run("ScaledUp", func(t *testing.T) {
+		requeueAfter, err := RequeueAfter(dfv1.Step{}, 1, 0)
+		assert.NoError(t, err)
+		assert.Equal(t, time.Duration(0), requeueAfter)
+	})
+	t.Run("NoPeek", func(t *testing.T) {
+		requeueAfter, err := RequeueAfter(dfv1.Step{
+			Spec: dfv1.StepSpec{
+				Scale: dfv1.Scale{ScalingDelay: `"4m"`},
+			},
+		}, 0, 1)
+		assert.NoError(t, err)
+		assert.Equal(t, time.Duration(0), requeueAfter)
+	})
+	t.Run("NoPeek", func(t *testing.T) {
+		requeueAfter, err := RequeueAfter(dfv1.Step{
+			Spec: dfv1.StepSpec{
+				Scale: dfv1.Scale{ScalingDelay: `"4m"`},
+			},
+		}, 0, 0)
+		assert.NoError(t, err)
+		assert.Equal(t, 4*time.Minute, requeueAfter)
+	})
+}