refactor: architecture cleanup#876
Merged
gildesmarais merged 11 commits intofeat/revamp-frontendfrom Mar 14, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors the feed-serving architecture by introducing a shared “feed pipeline” (RequestParser → Resolver → Service → renderers → HTTP response writer) and removing the legacy feed generation/runtime components. It also updates request specs/OpenAPI artifacts and adds a focused test suite for the new pipeline.
Changes:
- Introduce new
Html2rss::Web::Feeds::*andHtml2rss::Web::Http::*modules to unify static + token feed rendering and response handling. - Remove the previous legacy feed generator/runtime/handlers and update app wiring (
AppContext, routes, and API handler). - Expand/adjust RSpec coverage and regenerate OpenAPI + frontend types; tweak RuboCop configuration.
Reviewed changes
Copilot reviewed 43 out of 45 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/support/openapi.rb | Normalizes OpenAPI output ordering via deep sort to stabilize diffs. |
| spec/smoke/docker_spec.rb | Removes inline RuboCop disables; smoke spec still validates dockerized API endpoints. |
| spec/html2rss/web/http/feed_response_spec.rb | Adds unit tests for the new HTTP feed response writer (status, cache headers). |
| spec/html2rss/web/feeds/service_spec.rb | Adds unit tests for feed service success/empty/error + caching behavior. |
| spec/html2rss/web/feeds/rss_renderer_spec.rb | Adds unit tests for RSS rendering behavior. |
| spec/html2rss/web/feeds/resolver_spec.rb | Adds unit tests for static/token request resolution and generator input normalization. |
| spec/html2rss/web/feeds/request_parser_spec.rb | Adds unit tests for parsing route inputs into a normalized feed request contract. |
| spec/html2rss/web/feeds/json_renderer_spec.rb | Adds unit tests for JSON feed empty-feed rendering path. |
| spec/html2rss/web/feeds/cache_spec.rb | Adds unit tests for the new in-memory feed result cache. |
| spec/html2rss/web/feed_runtime_spec.rb | Removes specs for the deleted async/stale-refresh runtime. |
| spec/html2rss/web/feed_accept_header_spec.rb | Adds tests for Accept header negotiation edge-cases. |
| spec/html2rss/web/app_spec.rb | Updates app specs to use the new feed pipeline + adds HEAD/service-failure cases. |
| spec/html2rss/web/app_integration_spec.rb | Updates integration specs to stub the new service + renderers and covers negotiation/HEAD. |
| spec/html2rss/web/api/v1_spec.rb | Updates API v1 specs to the new pipeline and adds service-failure json-feed assertions. |
| spec/html2rss/web/account_manager_spec.rb | Removes inline RuboCop disables; behavior assertions unchanged. |
| frontend/src/api/generated/types.gen.ts | Updates generated client types to match regenerated OpenAPI. |
| docs/api/v1/openapi.yaml | Regenerates OpenAPI (mostly ordering/shape updates for feed endpoints). |
| docs/adr/0006-app-context.md | Updates ADR to reflect removal of runtime/feed handler wiring. |
| app/routes/static.rb | Updates comment wording (“legacy” → “static”). |
| app/http/feed_route_handler.rb | New static feed route handler that runs requests through the shared pipeline and emits observability events. |
| app/http/feed_response.rb | New response writer that applies status, content-type, cache headers, and uses renderers. |
| app/feeds/service.rb | New canonical feed service that calls Html2rss.feed, normalizes payload, and caches results. |
| app/feeds/rss_renderer.rb | New RSS renderer for ok/empty/error results. |
| app/feeds/result.rb | New result value object (Data.define) for shared feed pipeline outputs. |
| app/feeds/response_format.rb | New feed representation wrapper around existing FeedResponseFormat. |
| app/feeds/resolver.rb | New resolver for static and token-backed feeds, including auth + URL validation for token feeds. |
| app/feeds/resolved_source.rb | New resolved-source value object (Data.define). |
| app/feeds/request_parser.rb | New request parser for extracting representation/identifier/params into a request contract. |
| app/feeds/request.rb | New request value object (Data.define). |
| app/feeds/payload.rb | New normalized payload value object (Data.define). |
| app/feeds/json_renderer.rb | New JSON Feed renderer that maps RSS objects into JSON Feed output. |
| app/feeds/cache.rb | New synchronous in-memory cache for feed results. |
| app/feeds.rb | Removes legacy “generate_feed” interface. |
| app/feed_runtime.rb | Removes legacy async/stale-refresh runtime cache. |
| app/feed_route_handler.rb | Removes legacy route handler. |
| app/feed_request_handler.rb | Removes legacy request handler/TTL resolver. |
| app/feed_render_result.rb | Removes legacy render-result wrapper. |
| app/feed_generator.rb | Removes legacy generator that mixed rendering + empty-feed handling. |
| app/auto_source.rb | Removes now-obsolete generator wrapper methods. |
| app/app_context.rb | Removes runtime/request handler wiring from the app context. |
| app/api/v1/feeds/show_feed.rb | Refactors token feed rendering to use the shared pipeline + Http::FeedResponse. |
| app.rb | Replaces explicit requires with a glob require and switches static feeds to Http::FeedRouteHandler. |
| Makefile | Ensures openapi-verify also checks the generated frontend client/types. |
| Gemfile.lock | Bumps html2rss/html2rss-configs revisions and updates transitive dependencies. |
| .rubocop.yml | Updates RuboCop rules (line length + stricter RSpec example/expectation limits). |
You can also share your feedback on Copilot code review. Take the survey.
Comment on lines
+70
to
+75
| emit_failure( | ||
| context, | ||
| feed_name, | ||
| InternalServerError.new(result.error_message || result.message || HttpError::DEFAULT_MESSAGE) | ||
| ) | ||
| end |
Comment on lines
+93
to
+101
| def error_result(error, resolved_source, cache_key) | ||
| Result.new( | ||
| status: :error, | ||
| payload: nil, | ||
| message: HttpError::DEFAULT_MESSAGE, | ||
| ttl_seconds: resolved_source.ttl_seconds, | ||
| cache_key: cache_key, | ||
| error_message: error.message | ||
| ) |
Comment on lines
+23
to
+32
| def fetch(key, ttl_seconds:, cacheable: true) | ||
| entry = read_entry(key) | ||
| return entry.result if fresh?(entry) | ||
|
|
||
| result = yield | ||
| return result unless cacheable_result?(cacheable, result) | ||
|
|
||
| write_entry(key, ttl_seconds, result) | ||
| result | ||
| end |
Comment on lines
+199
to
+216
| '401': | ||
| content: | ||
| application/feed+json: | ||
| schema: | ||
| type: string | ||
| description: returns JSON Feed-shaped errors when requested by json extension | ||
| '403': | ||
| content: | ||
| application/xml: | ||
| schema: | ||
| type: string | ||
| '401': | ||
| description: returns unauthorized for invalid tokens | ||
| description: returns forbidden when auto source is disabled | ||
| '500': | ||
| content: | ||
| application/json: | ||
| application/feed+json: | ||
| schema: | ||
| type: object | ||
| properties: | ||
| success: | ||
| type: boolean | ||
| error: | ||
| type: object | ||
| properties: | ||
| message: | ||
| type: string | ||
| code: | ||
| type: string | ||
| required: | ||
| - message | ||
| - code | ||
| required: | ||
| - success | ||
| - error | ||
| description: Render feed by token | ||
| parameters: | ||
| - name: token | ||
| in: path | ||
| required: true | ||
| schema: | ||
| type: string | ||
| type: string | ||
| description: returns non-cacheable json feed errors when service generation |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces significant refactoring and modernization of the application's feed handling and code organization. The main focus is on removing legacy feed generation and response code, consolidating require statements, and introducing a more modular and pipeline-based approach for feed rendering. Additionally, there are updates to code style enforcement and minor Makefile improvements.
Feed handling and codebase refactoring:
FeedGenerator,FeedRenderResult,FeedRequestHandler,FeedRouteHandler) with a new, modular pipeline approach usingFeeds::RequestParser,Feeds::Resolver,Feeds::Service, andHttp::FeedResponse. This simplifies the flow and improves maintainability. ([[1]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-f965f92b425fb2f75d38b491b2625fe21b8af20b7666217546bce8a42b198ea4L9-R9),[[2]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-6c02f8cc2a159ca1004f707322973a17ac6a1e9d175a7ff9b57713f379e5430bL5-L11),[[3]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-6c02f8cc2a159ca1004f707322973a17ac6a1e9d175a7ff9b57713f379e5430bL31-R79),[[4]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-36ceea7bd7ac01437b1724c96e5d09b8a967b998ab02d579335641243e4ba97aL7-L8),[[5]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-36ceea7bd7ac01437b1724c96e5d09b8a967b998ab02d579335641243e4ba97aL66-L89),[[6]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-bf03b2c81491332291f18492a82a4cdc5e2781fec5b940ba474eca5feddf3c0bL1-L132),[[7]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-cdc5e997b333870fbd4569081d1d01279ce42c7ef625adac9a19adc723838854L1-L9),[[8]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-77fce394c2007e55494c14d0389b82e9af8cf6a0d277a800555b66410ccd7effL1-L65),[[9]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-cb4c35caa77fc501ae7cff186b3d4900a666b9a47f40325f99db46de260f3522L1-L81))app.rb) to require all Ruby files in theapp/directory dynamically, reducing manual require statements and improving scalability. ([app.rbL9-R9](https://github.com/html2rss/html2rss-web/pull/876/files#diff-f965f92b425fb2f75d38b491b2625fe21b8af20b7666217546bce8a42b198ea4L9-R9))App context and dependency management:
feed_runtime,feed_request_handler) fromAppContextand its dependency list, reflecting the new feed handling architecture. ([[1]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-baca189ed4797d9f6a3817e0048ea70ad8523202cabe8c28a5543a753c428f64L20-L21),[[2]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-baca189ed4797d9f6a3817e0048ea70ad8523202cabe8c28a5543a753c428f64L45-R43))Routing and handler updates:
Http::FeedRouteHandlerinstead of the legacyFeedRouteHandler, ensuring that all feed requests are processed through the new pipeline. ([app.rbL134-R112](https://github.com/html2rss/html2rss-web/pull/876/files#diff-f965f92b425fb2f75d38b491b2625fe21b8af20b7666217546bce8a42b198ea4L134-R112))Code style and tooling:
RSpec/DescribeClasscop for flexibility in test descriptions. ([[1]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-4f894049af3375c2bd4e608f546f8d4a0eed95464efcdea850993200db9fef5cR15-R17),[[2]](https://github.com/html2rss/html2rss-web/pull/876/files#diff-4f894049af3375c2bd4e608f546f8d4a0eed95464efcdea850993200db9fef5cR39-R47))[MakefileL92-R94](https://github.com/html2rss/html2rss-web/pull/876/files#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52L92-R94))