Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grapherをキャッシュ可能に #24

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft

Grapherをキャッシュ可能に #24

wants to merge 5 commits into from

Conversation

koriym
Copy link
Owner

@koriym koriym commented Jan 15, 2021

概要

コンテキストをセットするときにdoctrine/cacheオブジェクトを渡すとキャッシュが行われます。

use Doctrine\Common\Cache\ArrayCache;

$cache = new ArrayCache();
$tmpDir = __DIR__ . '/tmp';
Dii::setContext($contextClass, $cache, $tmpDir);

効果

以下のコストが節約されます。

  • 束縛バリデーション
  • 対象クラスの解析(引数やメソッドのリフレクション)
  • 依存グラフの構築
  • 全てのアノテーション読み込み
  • AOPのクラスファイル生成

グラファーの生成は全てのDI/AOP束縛をループして対象を検査し、シンタックスツリーを生成しPHPコードを出力する高コストなものです。そのコストをランタイムで0にします。

バージョン

  • Dii::setContext()でのコンテキストの指定が必須になります。指定していない時のディフォルトコンテキストはありません。
  • アンターゲット束縛が必須になります。

以上の二点で後方互換性が破壊されるのでバージョンは0.4になります。

パフォーマンス以外の問題点

  • v0.3で束縛されていないクラスに対してランタイムでの暗黙的束縛が行われていましたが、この暗黙的束縛はAOPのコンパイルが行われておらず、同じ対象コードでも明示的束縛をしたときと振る舞いが変わっていました。

例)

/** @Loggable */
public functinn foo(){

明示的束縛の強制によるメリット

アンターゲット束縛の明示的な束縛には、以下のメリットもあると考えました。

  • インジェクター(Grapher)がミュータブルになり、より安定します。
  • ランタイムでの依存解決のエラーを抑止し、コンパイルタイム(アプリケーション初期化時)で依存解決の問題が分かります。
  • ディプロイ時のウオームキャッシュの生成が可能になります。
  • 一貫したAOPの適用ルール
  • Diiのコードは簡潔になります。 diff
  • 初期化時に束縛が完了しているので、デバッカーを使った確認も容易です。

デメリットは以下のようなものが検討されました。

  • 束縛のコードが必要
  • OSS側での過剰な制御

対策

束縛のコードが必要な対策として、フォルダをスキャンして束縛するモジュールの用意が考えられます。(必要なら別PRで)

// 一例
$this->install(new UntargetedModule([$classDir]);

パフォーマンスコストの性質

現状では束縛が増えるのに応じて、実行時のパフォーマンスは悪化しますがこのPRによる改良ではコストを初期化時に寄せる事ができます。

設計指針

メンテナンスしやしくパフォーマンスの良いコードを実現するために、オブジェクトの状態を安定的にしランタイムでより少ないコード実行を行うような指針を持っています。このPRはその指針に基づいたものです。

Summary by CodeRabbit

  • New Features

    • Introduced caching functionality using doctrine/cache.
  • Enhancements

    • Improved dependency injection configuration with new bindings for SiteController and FakeSiteController.
  • Refactor

    • Refactored the Dii class to enhance caching and object instantiation processes.
  • Tests

    • Updated unit tests to include context setting for better test initialization.

@koriym koriym added the enhancement New feature or request label Jan 15, 2021
Copy link

coderabbitai bot commented Jun 9, 2024

Warning

Rate limit exceeded

@koriym has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 33 minutes and 43 seconds before requesting another review.

How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Commits

Files that changed from the base of the PR and between b0d41aa and 856fe2f.

Walkthrough

The changes introduce a new dependency on Doctrine Cache and refactor the Dii class to utilize caching for improved performance. Additionally, the AppModule files in both the main and test directories have been updated to bind controllers, and the DiiTest class now initializes context in its setup method. These updates enhance dependency injection and caching mechanisms within the project.

Changes

Files Change Summary
composer.json Added "doctrine/cache": "^1.10" to the list of dependencies under the "require" section.
demo/src-module/Module/AppModule.php Added use SiteController; and binding for SiteController in the configure method.
src/Dii.php Added Doctrine Cache imports, modified setContext method, and refactored createComponent.
tests/Fake/Module/AppModule.php Added binding for FakeSiteController in the configure method.
tests/UnitTest/DiiTest.php Added Dii::setContext(App::class); call in the setUp() method.

Sequence Diagram(s)

sequenceDiagram
    participant Composer as composer.json
    participant AppModule as AppModule.php
    participant Dii as Dii.php
    participant Cache as Doctrine Cache
    participant Test as DiiTest.php

    Composer->>AppModule: Add doctrine/cache dependency
    AppModule->>Dii: Import and bind SiteController
    Dii->>Cache: Use Doctrine Cache
    Dii->>Test: Modify setContext method
    Test->>Dii: Initialize context in setUp method
Loading

Poem

In the code where changes flow,
A cache now helps the data grow.
Controllers bound in modules bright,
Enhancing tests with newfound might.
With Doctrine's touch, we now foresee,
A smoother path for Dii to be.
🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 54be58a and b0d41aa.

Files selected for processing (5)
  • composer.json (1 hunks)
  • demo/src-module/Module/AppModule.php (2 hunks)
  • src/Dii.php (4 hunks)
  • tests/Fake/Module/AppModule.php (1 hunks)
  • tests/UnitTest/DiiTest.php (1 hunks)
Additional comments not posted (9)
demo/src-module/Module/AppModule.php (2)

8-8: The import of SiteController is correctly placed and necessary for the binding within the configure method.


23-23: The binding of SiteController is correctly implemented and aligns with the PR's objective to enhance module configuration.

tests/Fake/Module/AppModule.php (1)

22-22: The binding of FakeSiteController is correctly implemented for testing purposes and aligns with the PR's objective to enhance the testing setup.

composer.json (2)

21-21: The update to the ray/di version is appropriate and likely necessary for compatibility with the new features introduced in the PR.


22-22: The addition of doctrine/cache is essential for the new caching capabilities introduced in the PR and is correctly added to the dependencies.

tests/UnitTest/DiiTest.php (1)

20-20: The addition of Dii::setContext(App::class) in the setUp method is correctly implemented to align with the new requirement that setting the context is mandatory before running tests.

src/Dii.php (3)

8-9: Imports for Doctrine\Common\Cache\ArrayCache and Doctrine\Common\Cache\Cache have been added.

These imports are necessary for the new caching functionality introduced in the setContext method.


37-38: Initialization of a private static variable $grapher of type Grapher.

This change aligns with the refactoring to use Grapher for dependency injection and object creation.


75-76: Use of Grapher instance to create new instances if the class is injectable.

This change is part of the refactoring to utilize Grapher for object instantiation, improving the flexibility and maintainability of the component creation process.

Comment on lines +43 to +56
public static function setContext(string $contextClass, ?Cache $cache = null, ?string $tmpDir = null): void
{
if (! class_exists($context)) {
throw new LogicException("Unloadable: {$context}");
$cache = $cache ?? new ArrayCache();
$tmpDir = $tmpDir ?? dirname((new ReflectionClass($contextClass))->getFileName()) . '/tmp';
if (! class_exists($contextClass)) {
throw new LogicException("Not found context class: {$contextClass}");
}

assert(class_exists($context));
self::$context = $context;
self::createModule();
/** @var ?Grapher $cachedModule */
self::$grapher = $cache->fetch($contextClass);
if (! self::$grapher instanceof Grapher) {
$module = (new $contextClass())();
self::$grapher = new Grapher($module, $tmpDir);
}
Copy link

Choose a reason for hiding this comment

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

Significant changes to the setContext method to support caching.

The method now accepts optional parameters for cache and temporary directory, and includes logic to handle caching of the Grapher instance. Consider adding detailed documentation about the behavior when cache is not provided or is empty, and the implications of using a default ArrayCache.

+ /**
+  * Sets the application context and initializes caching.
+  * @param string $contextClass The context class name.
+  * @param Cache|null $cache Optional cache backend to use.
+  * @param string|null $tmpDir Optional temporary directory for cache files.
+  * @throws LogicException If the context class is not found.
+  */
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
public static function setContext(string $contextClass, ?Cache $cache = null, ?string $tmpDir = null): void
{
if (! class_exists($context)) {
throw new LogicException("Unloadable: {$context}");
$cache = $cache ?? new ArrayCache();
$tmpDir = $tmpDir ?? dirname((new ReflectionClass($contextClass))->getFileName()) . '/tmp';
if (! class_exists($contextClass)) {
throw new LogicException("Not found context class: {$contextClass}");
}
assert(class_exists($context));
self::$context = $context;
self::createModule();
/** @var ?Grapher $cachedModule */
self::$grapher = $cache->fetch($contextClass);
if (! self::$grapher instanceof Grapher) {
$module = (new $contextClass())();
self::$grapher = new Grapher($module, $tmpDir);
}
/**
* Sets the application context and initializes caching.
* @param string $contextClass The context class name.
* @param Cache|null $cache Optional cache backend to use.
* @param string|null $tmpDir Optional temporary directory for cache files.
* @throws LogicException If the context class is not found.
*/
public static function setContext(string $contextClass, ?Cache $cache = null, ?string $tmpDir = null): void
{
$cache = $cache ?? new ArrayCache();
$tmpDir = $tmpDir ?? dirname((new ReflectionClass($contextClass))->getFileName()) . '/tmp';
if (! class_exists($contextClass)) {
throw new LogicException("Not found context class: {$contextClass}");
}
/** @var ?Grapher $cachedModule */
self::$grapher = $cache->fetch($contextClass);
if (! self::$grapher instanceof Grapher) {
$module = (new $contextClass())();
self::$grapher = new Grapher($module, $tmpDir);
}

koriym added 2 commits June 9, 2024 09:45
The import statements within Dii.php have been rearranged. The use statement for Doctrine's "AnnotationRegistry" has been repositioned higher in the list to better reflect its relevance within the code.
@koriym koriym marked this pull request as draft June 9, 2024 00:52
@koriym
Copy link
Owner Author

koriym commented Jun 9, 2024

doctrine/cacheが非推奨になっているので一旦draftにします。
https://www.doctrine-project.org/projects/doctrine-cache/en/2.2/index.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant