Skip to content

feat: Add DI container framework + core test infrastructure#1631

Open
bthebladeprimer wants to merge 3 commits into
bn/feature/cc-01-build-configfrom
bn/feature/cc-02-di-container
Open

feat: Add DI container framework + core test infrastructure#1631
bthebladeprimer wants to merge 3 commits into
bn/feature/cc-01-build-configfrom
bn/feature/cc-02-di-container

Conversation

@bthebladeprimer
Copy link
Copy Markdown
Contributor

Summary

  • Add custom actor-based DI container framework (12 source files) with transient, singleton, and weak retention policies
  • Add async/await resolution, SwiftUI environment integration, container diagnostics, and health checks
  • Add core test infrastructure: XCTestCase+Async (async stream helpers), ContainerTestHelpers, TestData base
  • Add comprehensive DI test suite (11 test files)

Context

This is PR 2 of 15 in the CheckoutComponents PR split. The DI framework is the foundation — all CheckoutComponents code resolves dependencies through this container.

Depends on: PR 1 (Build Config) — #1630
Tracking: Notion PR Review Tracker

Key files

  • Internal/DI/Framework/Container.swift — Core container implementation (actor-based)
  • Internal/DI/Framework/DIContainer.swift — Singleton managing container lifecycle
  • Internal/DI/Framework/Factory.swift — Factory pattern for parameterized creation
  • Internal/DI/Framework/RetentionStrategy.swift — Memory management policies
  • TestSupport/XCTestCase+Async.swift — Async stream testing utilities

Test plan

  • Run DI test suite: xcodebuild test -only-testing:"Tests/DIContainerTests"
  • Review thread safety of actor-based container
  • Review retention policies (singleton, transient, weak)
  • Verify no retain cycles in factory closures

@bthebladeprimer bthebladeprimer requested a review from a team as a code owner March 26, 2026 15:34
@bthebladeprimer bthebladeprimer self-assigned this Mar 26, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 26, 2026

Warnings
⚠️ > Pull Request size seems relatively large. If this Pull Request contains multiple changes, please split each into separate PR will helps faster, easier review.

Generated by 🚫 Danger Swift against 01baa63

@bthebladeprimer bthebladeprimer marked this pull request as draft March 26, 2026 16:31
@bthebladeprimer bthebladeprimer marked this pull request as ready for review April 3, 2026 18:09
///
/// - Warning: The semaphore-based fallback blocks the calling thread while
/// waiting for actor-isolated async work. If called from the Swift
/// cooperative thread pool (e.g. inside a `Task`) this can deadlock
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.

Can we do any better here, is there a way to not have this deadlock risk, or add a runtime assertion so it is unreachable from async contexts?

if let stored = await container.getInstance(forKey: key) {
return stored
}
await container.setInstance(new, forKey: key)
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.

We fetch stored twice here, but it is not clear from the code flow where or how stored is used. Is this relying on a side-effect?

Comment thread pr-review-findings-v1.md
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.

These PR review findings should not ship with the PR

// MARK: - Diagnostics

/// Get diagnostic information about the container state
public func getDiagnostics() -> ContainerDiagnostics {
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.

Does this need to be public? Not sure how useful this information would be to a merchant.

// Copyright © 2026 Primer API Ltd. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.

// TODO: Rename file to DIContainer+SwiftUI.swift
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.

Should we rename this file now?

name: String? = nil
) async throws -> Self {
let builder = register(F.self)
let namedBuilder = name != nil ? builder.named(name!) : builder
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.

if let name instead of name!?

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.

I think you could also do name.map(builder.named) ?? builder

Add custom actor-based dependency injection framework with support for
transient, singleton, and weak retention policies. Includes async/await
resolution, SwiftUI environment integration, container diagnostics,
and health checks. Ships with core test utilities (XCTestCase+Async,
ContainerTestHelpers, TestData) and comprehensive DI test suite.
@bthebladeprimer bthebladeprimer force-pushed the bn/feature/cc-02-di-container branch from 637b7c4 to 01baa63 Compare April 15, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants