Skip to content

Commit 2cb6baf

Browse files
committed
WIP: Recycle / Observers
1 parent 314ecc8 commit 2cb6baf

23 files changed

Lines changed: 2075 additions & 965 deletions

File tree

bench/tx-centrifuge/README.md

Lines changed: 237 additions & 25 deletions
Large diffs are not rendered by default.

bench/tx-centrifuge/app/Main.hs

Lines changed: 154 additions & 95 deletions
Large diffs are not rendered by default.

bench/tx-centrifuge/data/config-multi-group.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
"type": "value",
1111
"params": {
1212
"fee": 200000
13-
}
13+
},
14+
"recycle": { "type": "on_pull" }
1415
},
16+
1517
"workloads": {
1618
"group-01": {
1719
"rate_limit": {

bench/tx-centrifuge/data/config-per-target-0_2.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
"type": "value",
1111
"params": {
1212
"fee": 200000
13-
}
13+
},
14+
"recycle": { "type": "on_pull" }
1415
},
16+
1517
"workloads": {
1618
"default": {
1719
"rate_limit": {

bench/tx-centrifuge/data/config-per-target-200.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
"type": "value",
1111
"params": {
1212
"fee": 200000
13-
}
13+
},
14+
"recycle": { "type": "on_pull" }
1415
},
16+
1517
"workloads": {
1618
"default": {
1719
"rate_limit": {

bench/tx-centrifuge/data/config-per-target-2k.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
"type": "value",
1111
"params": {
1212
"fee": 200000
13-
}
13+
},
14+
"recycle": { "type": "on_pull" }
1415
},
16+
1517
"workloads": {
1618
"default": {
1719
"rate_limit": {

bench/tx-centrifuge/data/config-shared-10.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
"type": "value",
1111
"params": {
1212
"fee": 200000
13-
}
13+
},
14+
"recycle": { "type": "on_pull" }
1415
},
16+
1517
"workloads": {
1618
"default": {
1719
"rate_limit": {

bench/tx-centrifuge/data/config-shared-100k.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
"type": "value",
1111
"params": {
1212
"fee": 200000
13-
}
13+
},
14+
"recycle": { "type": "on_pull" }
1415
},
16+
1517
"workloads": {
1618
"default": {
1719
"rate_limit": {

bench/tx-centrifuge/lib/pull-fiction/Cardano/Benchmarking/PullFiction/Config/Raw.hs

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@ module Cardano.Benchmarking.PullFiction.Config.Raw
2424
-- * Config.
2525
Config (..)
2626

27+
-- * Observer.
28+
, Observer (..)
29+
2730
-- * Builder.
2831
, Builder (..)
2932

33+
-- * Recycle strategy.
34+
, RecycleStrategy (..)
35+
3036
-- * RateLimit.
3137
, RateLimit (..)
3238
-- ** TopLevelScope.
@@ -74,6 +80,10 @@ data Config = Config
7480
{ -- | Raw JSON value describing how to load initial inputs.
7581
-- Interpretation is left to the caller (e.g. @Main.hs@).
7682
initialInputs :: !Aeson.Value
83+
-- | Optional @\"observers\"@ map (keyed by name).
84+
-- Because Aeson decodes JSON objects into a 'Map', duplicate observer names
85+
-- are silently discarded (last value wins).
86+
, maybeObservers :: !(Maybe (Map String Observer))
7787
-- | Optional top level @\"builder\"@.
7888
, maybeTopLevelBuilder :: !(Maybe Builder)
7989
-- | Optional top-level @\"rate_limit\"@.
@@ -82,22 +92,45 @@ data Config = Config
8292
, maybeTopLevelMaxBatchSize :: !(Maybe Natural)
8393
-- | Optional top-level @\"on_exhaustion\"@.
8494
, maybeTopLevelOnExhaustion :: !(Maybe OnExhaustion)
85-
-- | Generator workloads keyed by name. Because Aeson decodes JSON objects
86-
-- into a 'Map', duplicate workload names are silently discarded (last
87-
-- value wins).
88-
, workloads :: !(Map String Workload)
95+
-- | Optional generator workloads keyed by name.
96+
-- Because Aeson decodes JSON objects into a 'Map', duplicate workload names
97+
-- are silently discarded (last value wins).
98+
, maybeWorkloads :: !(Maybe (Map String Workload))
8999
}
90100
deriving (Show, Eq)
91101

92102
instance Aeson.FromJSON Config where
93103
parseJSON = Aeson.withObject "Config" $ \o ->
94104
Config
95105
<$> o .: "initial_inputs"
106+
<*> o .:? "observers"
96107
<*> o .:? "builder"
97-
<*> Aeson.Types.explicitParseFieldMaybe parseTopLevelRateLimit o "rate_limit"
108+
<*> Aeson.Types.explicitParseFieldMaybe parseTopLevelRateLimit o
109+
"rate_limit"
98110
<*> o .:? "max_batch_size"
99111
<*> o .:? "on_exhaustion"
100-
<*> o .: "workloads"
112+
<*> o .:? "workloads"
113+
114+
--------------------------------------------------------------------------------
115+
116+
-- | Opaque observer configuration.
117+
--
118+
-- Carries a @\"type\"@ discriminator and an opaque @\"params\"@ object.
119+
-- Interpretation of the params is the caller's responsibility (see @Main.hs@),
120+
-- just like 'initialInputs' and 'Builder'.
121+
data Observer = Observer
122+
{ -- | Observer variant name (e.g. @\"nodetonode\"@). Non-empty.
123+
observerType :: !String
124+
-- | Opaque params object for the variant.
125+
, observerParams :: !Aeson.Value
126+
}
127+
deriving (Show, Eq)
128+
129+
instance Aeson.FromJSON Observer where
130+
parseJSON = Aeson.withObject "Observer" $ \o -> do
131+
ty <- o .: "type" :: Aeson.Types.Parser String
132+
when (null ty) $ fail "Observer: \"type\" must be non-empty"
133+
Observer ty <$> o .: "params"
101134

102135
--------------------------------------------------------------------------------
103136

@@ -111,14 +144,40 @@ data Builder = Builder
111144
builderType :: !String
112145
-- | Opaque params object for the variant.
113146
, builderParams :: !Aeson.Value
147+
-- | Optional recycle strategy. 'Nothing' means no recycling.
148+
, builderRecycle :: !(Maybe RecycleStrategy)
114149
}
115150
deriving (Show, Eq)
116151

117152
instance Aeson.FromJSON Builder where
118153
parseJSON = Aeson.withObject "Builder" $ \o -> do
119154
ty <- o .: "type" :: Aeson.Types.Parser String
120-
when (null ty) $ fail "Builder: type must be non-empty"
155+
when (null ty) $ fail "Builder: \"type\" must be non-empty"
121156
Builder ty <$> o .: "params"
157+
<*> o .:? "recycle"
158+
159+
--------------------------------------------------------------------------------
160+
161+
-- | When to recycle transaction outputs back to the input queue.
162+
data RecycleStrategy
163+
-- | Recycle immediately after building, before entering the payload queue.
164+
= RecycleOnBuild
165+
-- | Recycle when a worker fetches the payload from the queue.
166+
| RecycleOnPull
167+
-- | Recycle when an observer confirms the payload. Carries the observer name.
168+
| RecycleOnConfirm !String
169+
deriving (Show, Eq)
170+
171+
instance Aeson.FromJSON RecycleStrategy where
172+
parseJSON = Aeson.withObject "RecycleStrategy" $ \o -> do
173+
ty <- o .: "type" :: Aeson.Types.Parser String
174+
case ty of
175+
"on_build" -> pure RecycleOnBuild
176+
"on_pull" -> pure RecycleOnPull
177+
"on_confirm" ->
178+
RecycleOnConfirm <$> o .: "params"
179+
_ -> fail $ "RecycleStrategy: unknown \"type\" " ++ show ty
180+
++ ", expected \"on_build\", \"on_pull\", or \"on_confirm\""
122181

123182
--------------------------------------------------------------------------------
124183

@@ -186,7 +245,7 @@ parseRateLimit scopeParser = Aeson.withObject "RateLimit" $ \o -> do
186245
rl <- TokenBucket <$> p .: "tps"
187246
pure (maybeScope, rl)
188247
_ -> fail $
189-
"RateLimit: unknown type " ++ show ty ++ ", expected \"token_bucket\""
248+
"RateLimit: unknown \"type\" " ++ show ty ++ ", expected \"token_bucket\""
190249

191250
parseTopLevelRateLimit :: Aeson.Value
192251
-> Aeson.Types.Parser (Maybe TopLevelScope, RateLimit)
@@ -242,8 +301,9 @@ data Workload = Workload
242301
, maybeMaxBatchSize :: !(Maybe Natural)
243302
-- | Optional on-exhaustion behaviour.
244303
, maybeOnExhaustion :: !(Maybe OnExhaustion)
245-
-- | Targets keyed by name. Duplicate target names are silently discarded
246-
-- (last value wins) because Aeson decodes JSON objects into a 'Map'.
304+
-- | Targets keyed by name.
305+
-- Because Aeson decodes JSON objects into a 'Map', duplicate target names
306+
-- are silently discarded (last value wins).
247307
, targets :: !(Map String Target)
248308
}
249309
deriving (Show, Eq)
@@ -252,7 +312,8 @@ instance Aeson.FromJSON Workload where
252312
parseJSON = Aeson.withObject "Workload" $ \o ->
253313
Workload
254314
<$> o .:? "builder"
255-
<*> Aeson.Types.explicitParseFieldMaybe parseWorkloadRateLimit o "rate_limit"
315+
<*> Aeson.Types.explicitParseFieldMaybe parseWorkloadRateLimit o
316+
"rate_limit"
256317
<*> o .:? "max_batch_size"
257318
<*> o .:? "on_exhaustion"
258319
<*> o .: "targets"

0 commit comments

Comments
 (0)