Commit 705e9b5
Feature/ddd (#159)
* Add DDD entity abstractions design spec
Defines the design for AggregateRoot, DomainEntity, ValueObject, and
IDomainEvent types to be added to RCommon.Entities. Extends existing
BusinessEntity hierarchy with zero breaking changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update DDD design spec with review feedback
Address spec review findings: add [Serializable] and [ConcurrencyCheck],
use block-scoped namespaces, add non-generic IAggregateRoot marker,
fix DomainEvents allocation via dual-list approach, thread-safe
GetHashCode, document graph walker behavior and known limitations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Address remaining spec review items
Add IEquatable<DomainEntity<TKey>> implementation, default! initializer
for Id, expand known-limitation documentation for dual-list sync bypass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add DDD entity abstractions implementation plan
TDD implementation plan for AggregateRoot, DomainEntity, ValueObject,
and IDomainEvent. 5 chunks, 25 steps, 69 tests covering all spec
scenarios including integration with IEntityEventTracker.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add IDomainEvent interface and DomainEvent base record
IDomainEvent extends ISerializableEvent with EventId and OccurredOn.
DomainEvent is an abstract record with sensible defaults.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add ValueObject abstract record
C# record-based value object with automatic structural equality,
immutability, and with-expression support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add DomainEntity<TKey> base class
Lightweight entity with identity-based equality and IEquatable support.
No event tracking — child entities raise events through aggregate root.
* feat: add AggregateRoot<TKey> and IAggregateRoot interfaces
Extends BusinessEntity<TKey> with domain event management, versioning,
and optimistic concurrency. Domain events flow through existing
IEntityEventTracker pipeline via AddLocalEvent delegation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Remove EntityEquals override from AggregateRoot
The 'new' keyword hiding of EntityEquals created polymorphic
inconsistency — callers through IBusinessEntity would get binary
comparison while callers through AggregateRoot got Id comparison.
Better tracked as a future improvement making EntityEquals virtual
on BusinessEntity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix async issues: ConfigureAwait(false), CancellationToken propagation, InMemoryEventBus memory leak
- Add ConfigureAwait(false) to ~150 await calls across all library projects
- Add CancellationToken to IEventBus.PublishAsync, IEventRouter.RouteEventsAsync,
and IEmailService.SendEmailAsync interfaces
- Propagate CancellationToken through DapperRepository.OpenAsync (13 sites),
Linq2DbRepository.DeleteAsync, all MediatR/Wolverine/MassTransit handler bridges,
and the event routing pipeline
- Refactor InMemoryEventBus to not capture IServiceCollection (memory leak),
track dynamic subscriptions internally and resolve via ActivatorUtilities
- Fix SendGridEmailService.SendEmailAsync missing return on empty recipients guard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add aggregate repository design spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: expand DDD spec to cover event dispatch, read models, and sagas
Adds three new design sections to the aggregate repository spec:
- Part 2: Automatic domain event dispatch via UnitOfWork post-commit hook
- Part 3: Read-model repositories (IReadModelRepository<T>, IPagedResult<T>)
- Part 4: Saga/process manager patterns (ISaga, IStateMachine, ISagaStore)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Implemented DDD related persistence.
* Updated Masstransit to use non-commercial version. Removed Autmapper as it has gone commercial.
* Updated specification pattern to be more comprehensive.
* Enabled ValueObject for DDD
* Added state machine implementations for Stateless and MassTransit.
* feat: add outbox core abstractions (IOutboxMessage, IOutboxStore, IOutboxSerializer, OutboxOptions)
* feat: add JsonOutboxSerializer with round-trip serialization and type safety
Implement JsonOutboxSerializer as IOutboxSerializer with:
- Serialize: Convert ISerializableEvent to JSON using System.Text.Json
- GetEventTypeName: Return short assembly-qualified type name for deserialization
- Deserialize: Reconstruct ISerializableEvent from type name and payload with validation
All 5 tests pass with coverage of happy path and error cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: two-phase UnitOfWork commit with PersistEventsAsync and CancellationToken propagation
- Add PersistEventsAsync(CT) to IEntityEventTracker for outbox phase-1 write
- Add CancellationToken to EmitTransactionalEventsAsync signature
- Implement PersistEventsAsync as no-op in InMemoryEntityEventTracker
- Pass CancellationToken through to IEventRouter.RouteEventsAsync
- Refactor UnitOfWork.CommitAsync to three-phase: persist events, commit tx, dispatch events
- Add Microsoft.Extensions.Hosting.Abstractions package refs to RCommon.Persistence.csproj
- Update all test mocks/verifies to match new interface signatures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add OutboxEventRouter with buffer-persist-dispatch pattern
Implements OutboxEventRouter as the transactional outbox IEventRouter: buffers events in-memory via AddTransactionalEvent(s), persists them as OutboxMessage rows via PersistBufferedEventsAsync (Phase 1, within active transaction), and dispatches pending messages via RouteEventsAsync (Phase 3, post-commit). Includes 6 unit tests covering buffering, persistence, field correctness, dispatch, and failure marking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add OutboxEntityEventTracker decorator for two-phase event persistence
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add OutboxProcessingService background poller with retry and dead-letter support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add AddOutbox<T> builder extension, UnitOfWork integration, and concurrency tests
Implements the AddOutbox<TOutboxStore>() extension on IPersistenceBuilder that wires
all outbox services (store, serializer, router, entity tracker, background processor)
into the DI container with correct lifetimes. Adds UnitOfWork integration test verifying
the two-phase PersistEventsAsync flow through OutboxEntityEventTracker, plus edge-case
concurrency tests for empty buffers, no-pending routing, and dead-letter exclusion.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add EFCoreOutboxStore with IDataStoreFactory, RetryCount filter, and SQLite tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add DapperOutboxStore with IDataStoreFactory and RetryCount filter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Linq2DbOutboxStore with IDataStoreFactory and RetryCount filter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add RCommon.MassTransit.Outbox wrapping native EF Core outbox
Introduces RCommon.MassTransit.Outbox project with IMassTransitOutboxBuilder,
MassTransitOutboxBuilder, and AddOutbox<TDbContext> extension method that wraps
MassTransit's IEntityFrameworkOutboxConfigurator into RCommon's builder pattern.
Includes test project with 4 passing unit tests covering UseSqlServer, UsePostgres,
UseBusOutbox delegation, and null-guard constructor validation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add RCommon.Wolverine.Outbox wrapping native durable messaging
Wraps Wolverine's WolverineFx.EntityFrameworkCore durable messaging with
RCommon's builder pattern via IWolverineOutboxBuilder, WolverineOutboxBuilder,
and WolverineOutboxBuilderExtensions. Includes test project with 8 passing
unit tests achieving 100% line/branch/method coverage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: add outbox projects to solution file
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: throttle outbox cleanup and document EF Core client-side ordering
- Add CleanupInterval option (default 1h) to avoid running DELETE queries
on every polling cycle
- Add clear comment explaining why EFCoreOutboxStore uses client-side
OrderBy (DateTimeOffset not supported in ORDER BY by all providers)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: ThenInclude chain was overwritten by RepositoryQuery getter
The RepositoryQuery getter always replaced _repositoryQuery with
_includableQueryable, discarding any ThenInclude results. Fixed by
nulling _includableQueryable after ThenInclude consumes it, and
having Include chain from _repositoryQuery when _includableQueryable
is null (preserving prior ThenInclude chains).
Affects both EFCoreRepository and EFCoreAggregateRepository.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Outbox V2 design spec
Covers exponential backoff, distributed locking (SQL Server + PostgreSQL),
dead letter replay, and inbox/idempotency with standalone and auto-check modes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: fix SQL Server ClaimAsync SQL and spec review issues
- Use CTE instead of UPDATE TOP for ordered claims
- Add UPDLOCK, ROWLOCK, READPAST hints for concurrent safety
- Clarify ConfigureAwait(false) requirement in pseudocode
- Fix inbox ConsumerType nullability description
- Add missing Dapper/Linq2Db builder extension files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: address spec review round 2 — OutboxEventRouter changes
- Add Section 4.4 documenting OutboxEventRouter V2 behavior
- RouteEventsAsync() no longer reads from store; dispatches retained events
- Failures left for background processor (no MarkFailedAsync call)
- Add missing test files to Section 8
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: fix spec review round 3 — router sketch and inbox ID clarity
- Add implementation sketch for OutboxEventRouter retained-event pattern
- Fix Mode 1 inbox example: use domain-specific ID, not @event.Id
- Clarify that ISerializableEvent has no Id property
- Document that Mode 1 requires consumer-chosen deduplication key
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Outbox V2 implementation plan
12-task plan covering backoff strategy, interface changes, inbox abstractions,
OutboxEventRouter V2, OutboxProcessingService V2, EF Core/Dapper/Linq2Db
store implementations, inbox stores, and full verification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add IBackoffStrategy, ExponentialBackoffStrategy, and V2 OutboxOptions
Introduces IBackoffStrategy interface and ExponentialBackoffStrategy implementation
for computing retry delays with configurable base delay, max delay, and multiplier.
Extends OutboxOptions with V2 properties: LockDuration, BackoffBaseDelay,
BackoffMaxDelay, BackoffMultiplier, and InboxTableName.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: V2 interface changes — ClaimAsync, backoff, locking, dead letter replay
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add IInboxStore, IInboxMessage, and InboxMessage abstractions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: OutboxEventRouter V2 — retained-event dispatch, no store reads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: OutboxProcessingService V2 — ClaimAsync, backoff, inbox auto-check
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: EFCoreOutboxStore V2 — ClaimAsync, dead letter replay, backoff
- Add ClaimAsync with optimistic LINQ fallback (works with SQLite in tests)
- Remove GetPendingAsync, replaced by ClaimAsync with locking semantics
- Update MarkFailedAsync to accept nextRetryAtUtc, clear lock fields
- Add GetDeadLettersAsync with offset/batchSize pagination
- Add ReplayDeadLetterAsync to reset all fields on dead-lettered messages
- Update SaveAsync to copy NextRetryAtUtc, LockedByInstanceId, LockedUntilUtc
- Add _tableName field from OutboxOptions
- Update OutboxMessageConfiguration with new columns and two new indexes
- Rewrite EFCoreOutboxStoreTests with 12 tests covering V2 behaviors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: EFCoreInboxStore — inbox/idempotency for EF Core
Adds EFCoreInboxStore (IInboxStore), InboxMessageConfiguration (composite PK on MessageId+ConsumerType), AddInboxMessages ModelBuilder extension, and 4 passing tests. TestOutboxDbContext updated to include inbox schema.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: DapperOutboxStore V2 — ClaimAsync, dead letter replay, backoff
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: DapperInboxStore — inbox/idempotency for Dapper
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: Linq2DbOutboxStore V2 — ClaimAsync, dead letter replay, backoff
- Add ILockStatementProvider to constructor with null guard
- Remove GetPendingAsync; add ClaimAsync with PostgreSQL/SQL Server raw SQL
- Update SaveAsync to copy NextRetryAtUtc, LockedByInstanceId, LockedUntilUtc
- Update MarkFailedAsync signature to include nextRetryAtUtc and clear locks
- Add GetDeadLettersAsync (LINQ) and ReplayDeadLetterAsync (LINQ update)
- Add UseLockStatementProvider<TProvider> to ILinq2DbPersistenceBuilder and Linq2DbPersistenceBuilder
- Update tests: add lock provider mock and NullLockStatementProvider test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: Linq2DbInboxStore — inbox/idempotency for Linq2Db
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Added outbox implementations for the stack.
* Moved projects to appropriate solution folder.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>1 parent b83bdcd commit 705e9b5
219 files changed
Lines changed: 21178 additions & 632 deletions
File tree
- Examples/CleanWithCQRS
- HR.LeaveManagement.Application.UnitTests
- LeaveTypes
- Commands
- Queries
- HR.LeaveManagement.Application
- Features
- LeaveAllocations/Handlers
- Commands
- Queries
- LeaveRequests/Handlers
- Commands
- Queries
- LeaveTypes/Handlers
- Commands
- Queries
- Mappings
- Profiles
- HR.LeaveManagement.Identity/Services
- HR.LeaveManagement.MVC
- Controllers
- Mappings
- Services
- Src
- RCommon.ApplicationServices/Validation
- RCommon.Core
- EventHandling
- Producers
- Extensions
- Reflection
- StateMachines
- RCommon.Dapper
- Crud
- Inbox
- Outbox
- Sagas
- RCommon.EfCore
- Crud
- Inbox
- Outbox
- Sagas
- RCommon.Emailing
- Smtp
- RCommon.Entities
- RCommon.FluentValidation
- RCommon.Linq2Db
- Crud
- Inbox
- Outbox
- Sagas
- RCommon.MassTransit.Outbox
- RCommon.MassTransit.StateMachines
- RCommon.MassTransit
- Producers
- Subscribers
- RCommon.Mediator
- RCommon.Mediatr
- Behaviors
- Producers
- Subscribers
- RCommon.Models
- RCommon.Persistence.Caching/Crud
- RCommon.Persistence
- Crud
- Inbox
- Outbox
- Sagas
- Transactions
- RCommon.SendGrid
- RCommon.Stateless
- RCommon.Wolverine.Outbox
- RCommon.Wolverine
- Producers
- Subscribers
- Tests
- RCommon.Core.Tests
- RCommon.Dapper.Tests
- RCommon.EfCore.Tests
- RCommon.Entities.Tests
- RCommon.Linq2Db.Tests
- RCommon.MassTransit.Outbox.Tests
- RCommon.MassTransit.StateMachines.Tests
- RCommon.MassTransit.Tests
- RCommon.Mediatr.Tests/Behaviors
- RCommon.Models.Tests
- RCommon.Persistence.Tests
- RCommon.Stateless.Tests
- RCommon.Wolverine.Outbox.Tests
- docs/superpowers
- plans
- specs
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 0 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | 11 | | |
13 | 12 | | |
14 | 13 | | |
| |||
Lines changed: 2 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
5 | 4 | | |
6 | 5 | | |
7 | 6 | | |
8 | | - | |
9 | 7 | | |
10 | 8 | | |
11 | 9 | | |
| |||
26 | 24 | | |
27 | 25 | | |
28 | 26 | | |
29 | | - | |
30 | | - | |
31 | 27 | | |
32 | 28 | | |
33 | 29 | | |
34 | 30 | | |
35 | 31 | | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | 32 | | |
45 | 33 | | |
46 | 34 | | |
| |||
56 | 44 | | |
57 | 45 | | |
58 | 46 | | |
59 | | - | |
| 47 | + | |
60 | 48 | | |
61 | 49 | | |
62 | 50 | | |
| |||
77 | 65 | | |
78 | 66 | | |
79 | 67 | | |
80 | | - | |
| 68 | + | |
81 | 69 | | |
82 | 70 | | |
83 | 71 | | |
Lines changed: 2 additions & 17 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
5 | | - | |
6 | 4 | | |
7 | 5 | | |
8 | 6 | | |
| |||
22 | 20 | | |
23 | 21 | | |
24 | 22 | | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | 23 | | |
39 | 24 | | |
40 | 25 | | |
| |||
46 | 31 | | |
47 | 32 | | |
48 | 33 | | |
49 | | - | |
50 | | - | |
| 34 | + | |
| 35 | + | |
51 | 36 | | |
52 | 37 | | |
53 | 38 | | |
| |||
Lines changed: 0 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
| |||
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
14 | | - | |
15 | | - | |
16 | 13 | | |
17 | 14 | | |
18 | 15 | | |
| |||
Lines changed: 1 addition & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
| |||
25 | 24 | | |
26 | 25 | | |
27 | 26 | | |
28 | | - | |
29 | 27 | | |
30 | 28 | | |
31 | 29 | | |
32 | 30 | | |
33 | 31 | | |
34 | | - | |
35 | 32 | | |
36 | 33 | | |
37 | 34 | | |
38 | 35 | | |
39 | 36 | | |
40 | 37 | | |
41 | 38 | | |
42 | | - | |
43 | 39 | | |
44 | 40 | | |
45 | 41 | | |
| |||
77 | 73 | | |
78 | 74 | | |
79 | 75 | | |
80 | | - | |
| 76 | + | |
81 | 77 | | |
82 | 78 | | |
83 | 79 | | |
84 | 80 | | |
85 | | - | |
86 | 81 | | |
87 | 82 | | |
88 | 83 | | |
| |||
Lines changed: 1 addition & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
| |||
17 | 16 | | |
18 | 17 | | |
19 | 18 | | |
20 | | - | |
21 | 19 | | |
22 | | - | |
| 20 | + | |
23 | 21 | | |
24 | 22 | | |
25 | 23 | | |
26 | | - | |
27 | 24 | | |
28 | 25 | | |
29 | 26 | | |
| |||
Lines changed: 2 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
5 | 4 | | |
| 5 | + | |
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
24 | 23 | | |
25 | 24 | | |
26 | 25 | | |
27 | 26 | | |
28 | | - | |
29 | 27 | | |
30 | 28 | | |
31 | 29 | | |
32 | 30 | | |
33 | 31 | | |
34 | 32 | | |
35 | | - | |
36 | 33 | | |
37 | 34 | | |
38 | 35 | | |
| |||
48 | 45 | | |
49 | 46 | | |
50 | 47 | | |
51 | | - | |
| 48 | + | |
52 | 49 | | |
53 | 50 | | |
54 | | - | |
55 | 51 | | |
56 | 52 | | |
57 | 53 | | |
Lines changed: 4 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
18 | 17 | | |
19 | | - | |
| 18 | + | |
20 | 19 | | |
21 | 20 | | |
22 | 21 | | |
23 | | - | |
24 | 22 | | |
| 23 | + | |
25 | 24 | | |
26 | 25 | | |
27 | 26 | | |
28 | 27 | | |
29 | | - | |
| 28 | + | |
30 | 29 | | |
31 | 30 | | |
32 | 31 | | |
Lines changed: 6 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
22 | | - | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
28 | 27 | | |
29 | 28 | | |
30 | 29 | | |
31 | 30 | | |
32 | 31 | | |
33 | | - | |
34 | 32 | | |
35 | 33 | | |
36 | 34 | | |
| |||
44 | 42 | | |
45 | 43 | | |
46 | 44 | | |
47 | | - | |
| 45 | + | |
48 | 46 | | |
49 | 47 | | |
50 | | - | |
| 48 | + | |
51 | 49 | | |
52 | 50 | | |
53 | 51 | | |
54 | 52 | | |
55 | 53 | | |
56 | 54 | | |
57 | 55 | | |
58 | | - | |
59 | | - | |
| 56 | + | |
| 57 | + | |
60 | 58 | | |
61 | 59 | | |
62 | 60 | | |
| |||
Lines changed: 8 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
5 | 4 | | |
| 5 | + | |
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
36 | 35 | | |
37 | 36 | | |
38 | 37 | | |
| |||
45 | 44 | | |
46 | 45 | | |
47 | 46 | | |
48 | | - | |
49 | 47 | | |
50 | 48 | | |
51 | 49 | | |
| |||
56 | 54 | | |
57 | 55 | | |
58 | 56 | | |
59 | | - | |
60 | | - | |
| 57 | + | |
61 | 58 | | |
62 | 59 | | |
63 | 60 | | |
| |||
67 | 64 | | |
68 | 65 | | |
69 | 66 | | |
70 | | - | |
71 | | - | |
| 67 | + | |
| 68 | + | |
72 | 69 | | |
73 | 70 | | |
74 | 71 | | |
| |||
82 | 79 | | |
83 | 80 | | |
84 | 81 | | |
85 | | - | |
| 82 | + | |
86 | 83 | | |
87 | 84 | | |
88 | 85 | | |
| |||
91 | 88 | | |
92 | 89 | | |
93 | 90 | | |
94 | | - | |
| 91 | + | |
95 | 92 | | |
96 | 93 | | |
97 | 94 | | |
| |||
104 | 101 | | |
105 | 102 | | |
106 | 103 | | |
107 | | - | |
| 104 | + | |
108 | 105 | | |
109 | 106 | | |
110 | 107 | | |
| |||
119 | 116 | | |
120 | 117 | | |
121 | 118 | | |
122 | | - | |
| 119 | + | |
123 | 120 | | |
124 | 121 | | |
125 | 122 | | |
| |||
0 commit comments