I have the following function from my odd-jobs job-queue library. There are a bunch of configuration parameters where the default implementation depends on another config parameter. For example:
cfgJobToHtmldepends oncfgJobType, which defaults todefaultJobType. However, after callingdefaultConfig, the user may choose to override the value forcfgJobTypewithout changingcfgJobToHtml. The expected behaviour is thatcfgJobToHtmlshould now use the user-provided value instead ofdefaultJobType.- Similarly,
cfgAllJobTypesdepends oncfgJobTypeSql, which in-turn defauls todefaultJobTypeSql. Again, after callingdefaultConfig, if the user overrides the value forcfgJobTypeSql, thencfgAllJobTypesshould use the overridden value, notdefaultJobTypeSql.
The code below does not work the way I'm expecting it to. If you change cfgJobType the change is not picked up by cfgJobToHtml. Similarly, for cfgJobTypeSql.
What is the best way to have these "dependent" default values?
-- | This function gives you a 'Config' with a bunch of sensible defaults
-- already applied. It requires the bare minimum arguments that this library
-- cannot assume on your behalf.
--
-- It makes a few __important assumptions__ about your 'jobPayload 'JSON, which
-- are documented in 'defaultJobType'.
defaultConfig :: (LogLevel -> LogEvent -> IO ()) -- ^ "Structured logging" function. Ref: 'cfgLogger'
-> TableName -- ^ DB table which holds your jobs. Ref: 'cfgTableName'
-> Pool Connection -- ^ DB connection-pool to be used by job-runner. Ref: 'cfgDbPool'
-> ConcurrencyControl -- ^ Concurrency configuration. Ref: 'cfgConcurrencyControl'
-> (Job -> IO ()) -- ^ The actual "job runner" which contains your application code. Ref: 'cfgJobRunner'
-> Config
defaultConfig logger tname dbpool ccControl jrunner =
let cfg = Config
{ cfgPollingInterval = defaultPollingInterval
, cfgOnJobSuccess = (const $ pure ())
, cfgOnJobFailed = []
, cfgJobRunner = jrunner
, cfgLogger = logger
, cfgDbPool = dbpool
, cfgOnJobStart = (const $ pure ())
, cfgDefaultMaxAttempts = 10
, cfgTableName = tname
, cfgOnJobTimeout = (const $ pure ())
, cfgConcurrencyControl = ccControl
, cfgPidFile = Nothing
, cfgJobType = defaultJobType
, cfgDefaultJobTimeout = Seconds 600
, cfgJobToHtml = defaultJobToHtml (cfgJobType cfg)
, cfgAllJobTypes = defaultDynamicJobTypes (cfgTableName cfg) (cfgJobTypeSql cfg)
, cfgJobTypeSql = defaultJobTypeSql
}
in cfg