@@ -658,16 +658,19 @@ class MethodBuilderTest
658
658
659
659
val stackClient = TestStackClient (stack, params)
660
660
val initialMethodBuilder = MethodBuilder .from(" with backups" , stackClient)
661
+ assert(initialMethodBuilder.config.backup == None )
662
+
661
663
val methodBuilder =
662
- initialMethodBuilder.withConfig(initialMethodBuilder.config.copy(backup = configuredBrfParam))
664
+ initialMethodBuilder.withConfig(
665
+ initialMethodBuilder.config.copy(backup = Some (configuredBrfParam)))
663
666
664
667
// Ensure BRF is configured before calling `nonIdempotent`
665
- assert(methodBuilder.config.backup == configuredBrfParam)
668
+ assert(methodBuilder.config.backup == Some ( configuredBrfParam) )
666
669
667
670
val nonIdempotentClient = methodBuilder.nonIdempotent
668
671
669
672
// Ensure BRF is disabled after calling `nonIdempotent`
670
- assert(nonIdempotentClient.config.backup == BackupRequestFilter .Disabled )
673
+ assert(nonIdempotentClient.config.backup == Some ( BackupRequestFilter .Disabled ) )
671
674
}
672
675
673
676
test(" nonIdempotent client keeps existing ResponseClassifier in params " ) {
@@ -796,8 +799,9 @@ class MethodBuilderTest
796
799
.idempotent(1 .percent, sendInterrupts = true , classifier)
797
800
798
801
mb.config.backup match {
799
- case BackupRequestFilter .Param
800
- .Configured (maxExtraLoadTunable, sendInterrupts, minSendBackupAfterMs) =>
802
+ case Some (
803
+ BackupRequestFilter .Param
804
+ .Configured (maxExtraLoadTunable, sendInterrupts, minSendBackupAfterMs)) =>
801
805
assert(
802
806
maxExtraLoadTunable().get == 1 .percent && sendInterrupts && minSendBackupAfterMs == 1 )
803
807
case _ => fail(" BackupRequestFilter not configured" )
@@ -862,8 +866,9 @@ class MethodBuilderTest
862
866
.idempotent(tunable, sendInterrupts = true , ResponseClassifier .Default )
863
867
864
868
assert(
865
- mb.config.backup == BackupRequestFilter
866
- .Configured (tunable, sendInterrupts = true )
869
+ mb.config.backup == Some (
870
+ BackupRequestFilter
871
+ .Configured (tunable, sendInterrupts = true ))
867
872
)
868
873
}
869
874
@@ -880,12 +885,13 @@ class MethodBuilderTest
880
885
.idempotent(tunable, sendInterrupts = true , ResponseClassifier .Default )
881
886
882
887
assert(
883
- mb.config.backup == BackupRequestFilter
884
- .Configured (tunable, sendInterrupts = true )
888
+ mb.config.backup == Some (
889
+ BackupRequestFilter
890
+ .Configured (tunable, sendInterrupts = true ))
885
891
)
886
892
887
893
val nonIdempotentMB = mb.nonIdempotent
888
- assert(nonIdempotentMB.config.backup == BackupRequestFilter .Disabled )
894
+ assert(nonIdempotentMB.config.backup == Some ( BackupRequestFilter .Disabled ) )
889
895
}
890
896
891
897
test(" idempotent combines existing classifier with new one" ) {
@@ -1122,6 +1128,100 @@ class MethodBuilderTest
1122
1128
assert(client.params[Retries .Budget ].retryBudget eq retryBudget)
1123
1129
}
1124
1130
1131
+ test(
1132
+ " BackupRequestFilter is configured with passed-in stack params when not configured in MethodBuilder" ) {
1133
+ val stats = new InMemoryStatsReceiver ()
1134
+ val timer = new MockTimer ()
1135
+ val params =
1136
+ Stack .Params .empty +
1137
+ param.Stats (stats) +
1138
+ param.Timer (timer) +
1139
+ BackupRequestFilter .Configured (maxExtraLoad = 0.01 , sendInterrupts = true )
1140
+
1141
+ val svc : Service [Int , Int ] = Service .mk { i =>
1142
+ Future .value(i)
1143
+ }
1144
+
1145
+ val stack = Stack .leaf(Stack .Role (" test" ), ServiceFactory .const(svc))
1146
+
1147
+ val stackClient = TestStackClient (stack, Stack .Params .empty).withParams(params)
1148
+ val mb = MethodBuilder .from(" mb" , stackClient)
1149
+
1150
+ Time .withCurrentTimeFrozen { tc =>
1151
+ val client = mb.newService(" a_client" )
1152
+ awaitResult(client(1 ))
1153
+
1154
+ tc.advance(10 .seconds)
1155
+ timer.tick()
1156
+ assert(stats.stats.contains(Seq (" mb" , " a_client" , " backups" , " send_backup_after_ms" )))
1157
+ }
1158
+ }
1159
+
1160
+ test(
1161
+ " BackupRequestFilter is configured with MethodBuilder idempotent configuration when also configured via stack params" ) {
1162
+ val stats = new InMemoryStatsReceiver ()
1163
+ val timer = new MockTimer ()
1164
+ val params =
1165
+ Stack .Params .empty +
1166
+ param.Stats (stats) +
1167
+ param.Timer (timer) +
1168
+ BackupRequestFilter .Disabled
1169
+
1170
+ val svc : Service [Int , Int ] = Service .mk { i =>
1171
+ Future .value(i)
1172
+ }
1173
+
1174
+ val stack = Stack .leaf(Stack .Role (" test" ), ServiceFactory .const(svc))
1175
+
1176
+ val stackClient = TestStackClient (stack, Stack .Params .empty).withParams(params)
1177
+ val classifier : ResponseClassifier = ResponseClassifier .named(" foo" ) {
1178
+ case ReqRep (_, Throw (_ : IndividualRequestTimeoutException )) =>
1179
+ ResponseClass .RetryableFailure
1180
+ }
1181
+
1182
+ // MB config should take precedence
1183
+ val mb = MethodBuilder .from(" mb" , stackClient).idempotent(0.05 , true , classifier)
1184
+
1185
+ Time .withCurrentTimeFrozen { tc =>
1186
+ val client = mb.newService(" a_client" )
1187
+ awaitResult(client(1 ))
1188
+
1189
+ tc.advance(10 .seconds)
1190
+ timer.tick()
1191
+ assert(stats.stats.contains(Seq (" mb" , " a_client" , " backups" , " send_backup_after_ms" )))
1192
+ }
1193
+ }
1194
+
1195
+ test(
1196
+ " BackupRequestFilter is configured with MethodBuilder nonIdempotent configuration when also configured via stack params" ) {
1197
+ val stats = new InMemoryStatsReceiver ()
1198
+ val timer = new MockTimer ()
1199
+ val params =
1200
+ Stack .Params .empty +
1201
+ param.Stats (stats) +
1202
+ param.Timer (timer) +
1203
+ BackupRequestFilter .Configured (maxExtraLoad = 0.01 , sendInterrupts = true )
1204
+
1205
+ val svc : Service [Int , Int ] = Service .mk { i =>
1206
+ Future .value(i)
1207
+ }
1208
+
1209
+ val stack = Stack .leaf(Stack .Role (" test" ), ServiceFactory .const(svc))
1210
+
1211
+ val stackClient = TestStackClient (stack, Stack .Params .empty).withParams(params)
1212
+ // MB config should take precedence
1213
+ val mb = MethodBuilder .from(" mb" , stackClient).nonIdempotent
1214
+
1215
+ Time .withCurrentTimeFrozen { tc =>
1216
+ val client = mb.newService(" a_client" )
1217
+ awaitResult(client(1 ))
1218
+
1219
+ tc.advance(10 .seconds)
1220
+ timer.tick()
1221
+ assert(! stats.stats.contains(Seq (" mb" , " a_client" , " backups" , " send_backup_after_ms" )))
1222
+ }
1223
+ }
1224
+
1125
1225
test(" shares RetryBudget between methods" ) {
1126
1226
val params = StackClient .defaultParams
1127
1227
0 commit comments