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.
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.
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.
Added or extended support for the following types that may appear in the
"value" property in CF specifications payload:
- Integer
- Double
- String
- Boolean (true and false)
- Null
Fixes#318
At some point in the past, Radarr altered its Preferred upper limit to
399 (from 395). As a result, these upper limits can no longer be
hard-coded the same way for all services. A new design has been
implemented to support distinct max and preferred limits for each
service.
Previously, quality item was split into a second part for only the
Preferred size settings, because at one point both Radarr and Sonarr
didn't support them the same. However, that has changed now so they are
now consolidated.
When preferred was null, it was not considered for change detection.
This was a regression likely introduced to support Radarr, which does
not have a preferred setting.
- Fixes#301
- Likely fixes#193 as well, which is a duplicate.
The cache system has been redesigned for extensibility and to support
caching data beyond Custom Formats. This is motivated by plans to cache
Quality Profiles to support the ability to do things like rename
profiles.
In rare circumstances outside of Recyclarr, quality profiles become
invalid due to missing required qualities. When this happens, users are
not even able to save the profile using the Sonarr or Radarr UI.
Recyclarr now detects this situation and automatically repairs the
quality profile by re-adding these missing qualities for users.
See: https://github.com/Radarr/Radarr/issues/9738
- Centralize sanitization into a custom Serilog enricher
- More log sites pass the exception object in
- Console output now consistently only prints the mssage, but not the
stack trace.
- File output always outputs the stack trace.
Additionally, there are fixes to several SonarLint issues.
To simplify logic in the system, a child lifetime scope is created for
each distinct configuration instance that is processed by Recyclarr. The
main driver for this is to avoid objects being reused between instances
and thus needing setup & teardown logic to deal with state.
Multiple path fragments are now supported in the built-in
`SubDirectory()` extension method, so there's no longer a need for the
custom `SubDir()` version.
It was previously located in Common, which I'm trying to gradually get
rid of. Supported services are ultimately determined by what is in the
guide, so that seems like the best place for it.
The removal of Sonarr v3 support (commit d45563cf) introduced a bug
resulting in media naming no longer working due to the `:4` key suffix
not being checked anymore.
Additionally, there were some tests under `src/tests/` that needed to be
moved to `tests/`. One of these tests in particular helped identify this
bug. Those tests have been moved to the appropriate location.
- `CustomFormatCache` is now a utility class for updating cache entries.
- `CustomFormatCacheData` is now what `CustomFormatCache` used to be
(data object used for serialization).
- `CustomFormatCachePersister` is now specific to custom formats. Future
cache types will have their own persister implementation.
This was originally put in place in commit b0bbb23d3 (from 2021) to
silence analysis warnings. However, I observed no warnings so this must
have been corrected in dotnet since then.