IEffectSettingsService

Lists the observational effects registered in this process, turns them on and off, and edits a configurable effect's settings. The dashboard's effects page and the GraphQL API's effects query and mutations both call it, so the two show the same values, refuse the same changes and write a setting the same way. Registered as scoped by AddScheduler(...).

Everything here is per process. The effect registry and each effect's settings object live in memory, with no persistence and no broadcast to other processes, so a change applies only to the process that served the call. A dashboard or API host is often not where trains run, and a restart restores the configured state.

Signature

namespace Trax.Scheduler.Services.Effects;
 
public interface IEffectSettingsService
{
    bool IsAvailable { get; }
    IReadOnlyList<EffectSettings> GetEffects();
    OperationResult SetEffectEnabled(string fullName, bool enabled);
    EffectConfigurationResult ConfigureEffect(string fullName, IReadOnlyDictionary<string, string?> values);
}
MemberWhat it does
IsAvailableWhether the host registered an effect registry (AddEffects does). Without one, GetEffects is empty and every change is refused
GetEffects()Every effect the registry tracks, ordered by the factory's full type name
SetEffectEnabled(fullName, enabled)Turns the effect whose factory has this full type name on or off. Refused, with nothing changed, for a name the registry does not track or an effect it tracks as not toggleable. Count is 1 on success
ConfigureEffect(fullName, values)Writes the named settings of a configurable effect, all or none (below)

EffectSettings

public record EffectSettings(
    string Name, string FullName, bool Enabled, bool Toggleable, bool IsConfigurable,
    string? ConfigurationTypeName, string? Configuration, IReadOnlyList<EffectSettingField> Fields);
 
public record EffectSettingField(
    string Name, string TypeName, EffectFieldKind Kind, bool Nullable, IReadOnlyList<string>? EnumValues,
    bool Sensitive, bool HasValue, string? Value, string Hint);
 
public enum EffectFieldKind { Boolean, Enum, Text, SetInCode }

Configuration is the settings object as JSON, with every member marked [TraxSensitive] written as {"_redacted": true}; it is null when the settings type cannot be written as JSON (it holds a delegate, say). Fields describes each public read-write property of the settings type, editable ones first:

FieldMeaning
NameThe property's name, which ConfigureEffect takes
TypeNameThe property's type, without Nullable<>, such as Int32
KindBoolean, Enum, Text (a number, string, date, time, duration, Guid or char), or SetInCode for any other type, which cannot be written here
NullableWhether no value is allowed
EnumValuesThe member names, for an enum
SensitiveThe property is marked [TraxSensitive], on itself, on the record parameter it comes from, on an interface property it implements, or on its type
HasValueWhether the setting holds a value
ValueThe current value as text, in the form ConfigureEffect reads back. Null when there is none, for SetInCode, and always for a sensitive setting
HintWhat to type, such as yyyy-MM-dd HH:mm:ss (UTC)

A sensitive setting's value is never returned. Writing one is allowed.

ConfigureEffect

public record EffectConfigurationResult(
    bool Success, int Count, string Message, IReadOnlyDictionary<string, string> Errors);

Turning off the parameter effect's saved outputs in this process:

var result = effectSettings.ConfigureEffect(
    "Trax.Effect.Provider.Parameter.Services.ParameterEffectProviderFactory.ParameterEffectProviderFactory",
    new Dictionary<string, string?> { ["SaveOutputs"] = "false" });

Each value is text, read as its property's type: numbers in invariant culture with . for the decimal point and no thousands separators, a date or time with no offset as UTC, a boolean as true or false, an enum by member name. Null or blank is no value for a property that accepts null, the empty string for a non-nullable string, and refused for anything else. The value must then pass the property's own ValidationAttributes.

Every value is read and checked before any is written. When one is refused, nothing is written and Errors names each refused setting with its reason; an unknown setting, and a SetInCode one, are refused the same way. When a setter throws part way, the settings already written are put back. A setting not named is not written, so a change made to it elsewhere in the meantime is kept. A change applies to the next run in this process.

Package

dotnet add package Trax.Scheduler