Skip to content

Improve Context Propagation and Payload Analysis - #49

Merged
viceroypenguin merged 15 commits into
mainfrom
context-payload
Jul 29, 2026
Merged

Improve Context Propagation and Payload Analysis#49
viceroypenguin merged 15 commits into
mainfrom
context-payload

Conversation

@viceroypenguin

@viceroypenguin viceroypenguin commented Jul 29, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features
    • Added build diagnostics for job request and job context types that can’t be serialized to JSON.
    • Introduced a dedicated payload analyzer to surface these issues during compilation.
    • Updated job context extractors to use a shared abstract base-class contract.
  • Bug Fixes
    • Improved validation to reject whitespace-only queue names.
    • Refined JSON-serialization rules (including common system value types and NodaTime).
  • Documentation
    • Added XML documentation comments to generated job helper methods.
  • Tests / Chores
    • Added payload analyzer tests; removed older analyzer test coverage and streamlined generator test helpers.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR replaces interface-based job context extractors with abstract base classes, adds recursive JSON serializability validation and diagnostics, refactors generator metadata and queue processing, updates related tests and snapshots, and changes repository configuration.

Changes

Serialization and context pipeline

Layer / File(s) Summary
Context extractor contract
src/Immediate.Jobs.Shared/JobContextPropagation.cs, src/Common/ITypeSymbolExtensions.cs, samples/*, tests/Immediate.Jobs.FunctionalTests/*
Context extractors now inherit from JobContextExtractor<TContext>, with symbol extensions resolving extractor context types through the new hierarchy.
Serialization validation and diagnostics
src/Common/PayloadValidation.cs, src/Immediate.Jobs.Analyzers/*
Recursive JSON serializability validation and new IJOB0013/IJOB0014 diagnostics replace the legacy validation flow.
Generator validation and JSON metadata
src/Immediate.Jobs.Generators/*
Generation validates payloads and contexts through the new API, reads queue settings from attributes, deduplicates context extractors, and rebuilds JSON metadata traversal.
Analyzer and generator test coverage
tests/Immediate.Jobs.Tests/*, tests/Immediate.Jobs.FunctionalTests/*
Tests cover payload diagnostics, updated extractor contracts, generated output assertions, invalid job scenarios, incremental test cleanup, and regenerated snapshot documentation.
Repository configuration
.editorconfig, coderabbit.yml, Immediate.Jobs.slnx, coverage-settings.xml
IDE diagnostic severities, CodeRabbit review settings, solution membership, test project ordering, and coverage exclusions are updated.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant JobSource
  participant PayloadAnalyzer
  participant PayloadValidation
  participant Generator
  participant JsonMetadataEmitter
  JobSource->>PayloadAnalyzer: analyze job and context symbols
  PayloadAnalyzer->>PayloadValidation: validate serializability
  PayloadValidation-->>PayloadAnalyzer: return validation result and locations
  JobSource->>Generator: transform job attributes
  Generator->>PayloadValidation: validate payload and context types
  Generator->>JsonMetadataEmitter: create JSON metadata
  JsonMetadataEmitter-->>Generator: return metadata model
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes around context propagation and payload analysis.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch context-payload

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
tests/Immediate.Jobs.Tests/GeneratorTests/ImmediateJobsGeneratorTests.cs (1)

331-332: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Incremental-caching coverage was dropped with the two removed tests.

EditingContextShapeInvalidatesOnlyOwningJobModel and EditingExtractorContractInvalidatesOnlyReferencingJobModel were the only assertions that context/extractor edits invalidate exactly the owning job model. Since this PR reworks how the transform reads context types, a caching regression (over- or under-invalidation) now has no test guarding it. Please re-add equivalents against the new extractor contract.

Want me to draft replacements for the new base-class shape?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Immediate.Jobs.Tests/GeneratorTests/ImmediateJobsGeneratorTests.cs`
around lines 331 - 332, Re-add incremental-caching tests equivalent to
EditingContextShapeInvalidatesOnlyOwningJobModel and
EditingExtractorContractInvalidatesOnlyReferencingJobModel, adapted to the new
extractor contract/base-class shape. Verify that context or extractor edits
invalidate exactly the owning or referencing job model, respectively, without
over- or under-invalidation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Common/ITypeSymbolExtensions.cs`:
- Around line 116-117: Update the RootNamespace property in
ITypeSymbolExtensions to null-propagate ContainingNamespace before accessing
RootNamespace, ensuring array symbols with no containing namespace return null
safely. Preserve the existing namespace resolution behavior for symbols that
have a containing namespace, including callers such as CreateTypeModel.

In `@src/Common/PayloadValidation.cs`:
- Around line 39-44: Update the type-argument and member traversal in the
relevant validation method so a false result from Visit is retained even when
reportError is supplied. Track whether any argument or member fails, continue
reporting remaining failures as needed, and return the accumulated failure
status at the method’s final return instead of unconditionally returning true.
- Around line 58-62: Update the rootNamespace == "System" handling in
PayloadValidation to avoid rejecting supported named collection shapes such as
List<T>, Dictionary<,>, and ImmutableArray<T>; add an allow path consistent with
the existing array handling. If named collections are intentionally unsupported,
retain the rejection and revise the reportError diagnostic to explicitly
describe that restriction.

In `@src/Immediate.Jobs.Generators/JsonMetadataEmitter.cs`:
- Around line 54-58: Update the HasParameterlessCreator assignment in the
metadata object initializer to require an accessible parameterless constructor,
rather than treating constructor == null as sufficient. Use the constructor
lookup result and its parameter list so ObjectCreator is emitted only when a
public zero-argument constructor exists.

---

Nitpick comments:
In `@tests/Immediate.Jobs.Tests/GeneratorTests/ImmediateJobsGeneratorTests.cs`:
- Around line 331-332: Re-add incremental-caching tests equivalent to
EditingContextShapeInvalidatesOnlyOwningJobModel and
EditingExtractorContractInvalidatesOnlyReferencingJobModel, adapted to the new
extractor contract/base-class shape. Verify that context or extractor edits
invalidate exactly the owning or referencing job model, respectively, without
over- or under-invalidation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 01937bf3-a938-481e-b68b-1cec7f2482ab

📥 Commits

Reviewing files that changed from the base of the PR and between 4fd05ca and c6c6edc.

📒 Files selected for processing (35)
  • .editorconfig
  • Immediate.Jobs.slnx
  • coderabbit.yml
  • samples/Aspire/Api/Context/RequestContext.cs
  • samples/NativeAot/Program.cs
  • src/Common/ITypeSymbolExtensions.cs
  • src/Common/JobDiscovery.cs
  • src/Common/PayloadValidation.cs
  • src/Immediate.Jobs.Analyzers/DiagnosticDescriptors.cs
  • src/Immediate.Jobs.Analyzers/DiagnosticIds.cs
  • src/Immediate.Jobs.Analyzers/ImmediateJobsAnalyzer.cs
  • src/Immediate.Jobs.Analyzers/JobClassAnalyzer.cs
  • src/Immediate.Jobs.Analyzers/PayloadAnalyzer.cs
  • src/Immediate.Jobs.Generators/ImmediateJobsGenerator.Transform.cs
  • src/Immediate.Jobs.Generators/JsonMetadataEmitter.cs
  • src/Immediate.Jobs.Generators/Templates/Job.sbntxt
  • src/Immediate.Jobs.Shared/JobContextPropagation.cs
  • tests/Immediate.Jobs.FunctionalTests/ContextPropagationTests.cs
  • tests/Immediate.Jobs.Tests/AnalyzerTests/ImmediateJobsAnalyzerTests.cs
  • tests/Immediate.Jobs.Tests/AnalyzerTests/PayloadAnalyzerTests.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/AddJobsTests.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/GeneratorTestHelper.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/ImmediateJobsGeneratorTests.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/InvalidJobsTests.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/AddJobsTests.ServiceCollectionExtensionsUsesQueuesAndTaggedRegistrations_framework=net10.0#IJ..WorkJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/ImmediateJobsGeneratorTests.ContextExtractorsGenerateOrderedCaptureRestoreMetadataAndScopedRegistrations#IJ..ContextualJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/ImmediateJobsGeneratorTests.CronJobGeneratesPayloadlessRecurringScheduler#IJ..CleanupSessionsJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/ImmediateJobsGeneratorTests.ExplicitJobDetailsOnValueTypeUsesConstrainedByReferenceAssignment#IJ..StructJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/ImmediateJobsGeneratorTests.InvokerDelegatesExecutionToImmediateHandlersPipeline#IJ..WorkJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/ImmediateJobsGeneratorTests.JobWithoutContextDoesNotEmitCaptureOrRestoreCode#IJ..PlainJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/ImmediateJobsGeneratorTests.NodaTimeContextUsesConfiguredGeneratedMetadata#IJ..ClockJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/ImmediateJobsGeneratorTests.PayloadJobGeneratesTypedSchedulerDirectInvokerAndRegistrations#IJ.Example.SendEmailJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/ImmediateJobsGeneratorTests.PayloadlessJobWithoutCronGeneratesDynamicRecurringScheduler#IJ..TenantCleanupJob.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/Snapshots/UnnameableJobsTests.ExplicitNameShouldRescueAnUnderivableClassName#IJ.Dummy.Job.g.verified.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/UnnameableJobsTests.cs
💤 Files with no reviewable changes (5)
  • src/Common/JobDiscovery.cs
  • src/Immediate.Jobs.Analyzers/DiagnosticDescriptors.cs
  • src/Immediate.Jobs.Analyzers/ImmediateJobsAnalyzer.cs
  • tests/Immediate.Jobs.Tests/AnalyzerTests/ImmediateJobsAnalyzerTests.cs
  • tests/Immediate.Jobs.Tests/GeneratorTests/GeneratorTestHelper.cs

Comment thread src/Common/ITypeSymbolExtensions.cs Outdated
Comment thread src/Common/PayloadValidation.cs
Comment thread src/Common/PayloadValidation.cs
Comment on lines +54 to +58
var constructorParameters = constructor?.Parameters ?? ImmutableArray<IParameterSymbol>.Empty;

return new()
{
HasParameterlessCreator = constructor is null || constructor.Parameters.Length == 0,
HasParameterlessCreator = constructor is null or { Parameters: [] },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how HasParameterlessCreator is consumed in the templates
rg -nP -C4 'HasParameterlessCreator' src

Repository: ImmediatePlatform/Immediate.Jobs

Length of output: 1821


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- JsonMetadataEmitter.cs (relevant sections) ---'
sed -n '1,170p' src/Immediate.Jobs.Generators/JsonMetadataEmitter.cs

echo
echo '--- any other HasParameterlessCreator usages ---'
rg -n 'HasParameterlessCreator' src

Repository: ImmediatePlatform/Immediate.Jobs

Length of output: 6535


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- references to JsonObjectRenderModel / ConstructorParameters / HasParameterlessCreator ---'
rg -n 'JsonObjectRenderModel|ConstructorParameters|HasParameterlessCreator' .

echo
echo '--- files that look like templates or generators ---'
git ls-files | rg '(\.tt$|Template|Generator|Emitter|RenderModel|Writer|CodeGen)'

Repository: ImmediatePlatform/Immediate.Jobs

Length of output: 7921


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- JsonMetadataEmitter surrounding model definitions ---'
sed -n '170,260p' src/Immediate.Jobs.Generators/JsonMetadataEmitter.cs

echo
echo '--- render/transform pipeline references to ObjectInfo / metadata ---'
rg -n -C3 'ObjectInfo|JsonMetadata|HasParameterlessCreator|ConstructorParameters' src/Immediate.Jobs.Generators

echo
echo '--- templates ---'
sed -n '1,260p' src/Immediate.Jobs.Generators/Templates/Job.sbntxt
echo
sed -n '1,260p' src/Immediate.Jobs.Generators/Templates/ServiceCollectionExtensions.sbntxt

Repository: ImmediatePlatform/Immediate.Jobs

Length of output: 28262


Check for an accessible parameterless ctor here, not constructor is null. GetConstructor returns null for any type with no public member-matching ctor, so this can still emit ObjectCreator = () => new T() for types that don’t actually have a public zero-arg constructor. src/Immediate.Jobs.Generators/JsonMetadataEmitter.cs:58

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Immediate.Jobs.Generators/JsonMetadataEmitter.cs` around lines 54 - 58,
Update the HasParameterlessCreator assignment in the metadata object initializer
to require an accessible parameterless constructor, rather than treating
constructor == null as sufficient. Use the constructor lookup result and its
parameter list so ObjectCreator is emitted only when a public zero-argument
constructor exists.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@coverage-settings.xml`:
- Around line 4-15: Update the ModulePaths exclusion pattern to also match the
Immediate.Jobs.Analyzers.dll and Immediate.Jobs.Generators.dll assemblies, while
preserving the existing Immediate.Handlers.Generators.dll exclusion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6232ee7a-6ca3-4e41-be74-cb99c8ccc7f5

📥 Commits

Reviewing files that changed from the base of the PR and between 1c41d5e and 8c49bd4.

📒 Files selected for processing (1)
  • coverage-settings.xml

Comment thread coverage-settings.xml
@coveralls

coveralls commented Jul 29, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 30488813255

Coverage increased (+4.8%) to 79.176%

Details

  • Coverage increased (+4.8%) from the base build.
  • Patch coverage: 42 uncovered changes across 5 files (242 of 284 lines covered, 85.21%).
  • 27 coverage regressions across 3 files.

Uncovered Changes

File Changed Covered %
src/Common/ITypeSymbolExtensions.cs 38 17 44.74%
src/Common/PayloadValidation.cs 60 48 80.0%
src/Immediate.Jobs.Generators/JsonMetadataEmitter.cs 62 56 90.32%
src/Immediate.Jobs.Analyzers/PayloadAnalyzer.cs 75 73 97.33%
src/Immediate.Jobs.Analyzers/JobClassAnalyzer.cs 3 2 66.67%
Total (8 files) 284 242 85.21%

Coverage Regressions

27 previously-covered lines in 3 files lost coverage.

File Lines Losing Coverage Coverage
src/Common/ITypeSymbolExtensions.cs 17 68.0%
src/Common/TypedConstantExtensions.cs 9 73.81%
src/Immediate.Jobs.Shared/JobSchedulerService.cs 1 89.21%

Coverage Stats

Coverage Status
Relevant Lines: 8692
Covered Lines: 6882
Line Coverage: 79.18%
Coverage Strength: 2.65 hits per line

💛 - Coveralls

@viceroypenguin
viceroypenguin merged commit 5c3e4de into main Jul 29, 2026
3 checks passed
@viceroypenguin
viceroypenguin deleted the context-payload branch July 29, 2026 20:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants