Previously, code was organized into projects that were too granular.
This resulted in slower solution builds in addition to added complexity.
Most class library projects have been consolidated into a single
project, Recyclarr.Core.
Added ISettings interface to allow injection of a specific subset of
settings into areas of code. This replaced the old ISettingsProvider
method of accessing settings.
- Consistently use ExitStatus enum.
- Where appropriate, do not handle exceptions in isolation in the
command class itself. Rather, let exceptions through to the entrypoint
so the centralized exception handler can deal with them.
This commit introduces significant changes to the initialization process
of Spectre.Console and the logging system:
1. Logger Initialization:
- Implement a two-phase initialization for the LoggerFactory.
- First phase creates an ILogger writing to the CLI console without
runtime configuration.
- Second phase wraps the initial logger with additional sinks (e.g.,
file logging) based on CLI arguments.
2. Spectre.Console Setup:
- Refactor AutofacTypeRegistrar to store registrations in lists.
- Implement Build() method to register types with Autofac when
called.
- This approach better aligns with Autofac's registration and
resolution separation.
3. Global Setup Tasks:
- Introduce AppDataDirSetupTask and LoggerSetupTask.
- Modify IGlobalSetupTask interface to accept BaseCommandSettings.
- Update existing setup tasks to conform to the new interface.
4. Error Handling:
- Implement top-level exception handling in Program.Main().
- Remove IFlurlHttpExceptionHandler interface, simplify
FlurlHttpExceptionHandler.
5. Logging Improvements:
- Move console logging setup to LoggerFactory.
- Introduce IndirectLoggerDecorator to allow dynamic logger updates.
- Simplify log template management.
6. Dependency Injection:
- Update CompositionRoot to reflect new logger and setup task
structure.
- Remove LoggingAutofacModule, integrate its functionality into
CompositionRoot.
These changes improve the flexibility and maintainability of the
application's startup process, particularly in handling logging and CLI
argument processing. The new structure allows for more dynamic
configuration of services based on runtime parameters.
Primary motivation for this change is to create separation of concerns
for log sink configuration. The LoggerFactory was becoming too large and
had too many responsibilities.
Later on this will help facilitate extension of log functionality while
respecting the Open Closed Principle.
I've made some updates to Recyclarr's CF "field" handling for
specifications, specifically addressing the issues regarding processing
language specifications
Here's a quick rundown of how Recyclarr processes fields for a language
spec after this change:
When loading the following fields from the guide:
```json
"fields": {
"value": 8,
"exceptLanguage": false
}
```
Recyclarr transforms it into the API-compatible format:
```json
"fields": [
{
"name": "value",
"value": 8
},
{
"name": "exceptLanguage",
"value": false
}
]
```
Next, it retrieves CF data from the API. For instance, if the API
returns:
```json
"fields": [
{
"name": "value",
"value": 10
},
{
"name": "foo",
"value": "bar"
},
{
"name": "exceptLanguage",
"value": true
}
]
```
Recyclarr compares the two sets of fields by matching the `name`
attributes from the guide to those from the API. Any fields present in
the API but absent in the guide are ignored. The values for matching
fields are then updated accordingly, and these changes are pushed back.
For this example:
- The field `value` is updated from `8` to `10`.
- The field `exceptLanguage` is updated from `false` to `true`.
- The field `foo` is ignored since there's no corresponding field in the
guide.