Code Monkey home page Code Monkey logo

bear.queryrepository's People

Contributors

jingu avatar kalibora avatar kawanamiyuu avatar koriym avatar kuma-guy avatar naokitsuchiya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

bear.queryrepository's Issues

@Cacheableアノテーション

現在の@QueryRepositoryは説明するときにCQRSの概念の説明が必要で、単なる時間キャッシュも同じように扱えるような初学者に分かりやすいアノテーション名が必要なのではないかと思いました。

AOPでのキャッシュはSpring / Go始め@Cacheableが一般的なようです。(同様に@Loggable / @Transactionalなど形容詞が一般的)

以下のように考えてみました。

単なる時間キャッシュ

/**
 * @Cacheable(expiry="short")
 */

指定しないと無制限

/**
 * @Cacheable
 */

// 下と同じ

/**
 * @Cacheable(expiry="never")
 */

update=trueでメソッドによるアップデートを可能に。これだとonPut(1, 'foo')のアクセスがあるとonGet(1)のキャッシュが再生成されます。

/**
 * @Cacheable(update=true)
 */

メソッドアップデートとキャッシュ時間を指定することもできます。

/**
 * @Cacheable(expiry="long"�, update=true)
 */

キャッシュ時間はshort, medium, longをinstall時に指定します。

時間を直接指定することもできます。

/**
 * @Cacheable(expirySecond=30�)
 */

CQRSパターンでは、Queryリポジトリをつくるためのジョブをキューに入れたり、それぞれのジョブをカスタムで持つことができますが、その機能は必要ならのちに作成することにして当面ニーズの強いキャッシュだけの機能にしぼればどうかと考えました。

どうでしょうか?

`@Refresh` の処理時に Uncaught TypeError が発生する

エラー時の画面を添付します。
image

詳細

以下のようなリソース定義があるとします。

namespace Sample\Resource\Page;

use BEAR\RepositoryModule\Annotation\Cacheable;
use BEAR\RepositoryModule\Annotation\Refresh;

/**
 * @Cacheable
 */
class Sample extends ResourceObject
{
    public function onGet(int $id) : ResourceObject
    {
        return $this;
    }

    /**
     * @Refresh(uri="page://self/sample?id={id}")
     */
    public function onPut(int $id, string $name) : ResourceObject
    {
        return $this;
    }
}

/sample?id=1&name=hgoe に対する put 処理が実行された後、BEAR\QueryRepository\CommandInterceptor から BEAR\QueryRepository\RefreshSameCommand::command() が実行されると思います。

この RefreshSameCommand はキャッシュのパージ処理実行後に、ターゲットとなるリソースの onGet メソッドが定義されている場合に呼び出しています。

https://github.com/bearsunday/BEAR.QueryRepository/blob/1.6.8/src/RefreshSameCommand.php#L28-L48

    public function command(MethodInvocation $invocation, ResourceObject $ro)
    {
        $method = $invocation->getMethod()->getName();
        if ($method === 'onGet' || $method === 'onPost') {
            return;
        }
        unset($invocation);
        $getQuery = $this->getQuery($ro);
        $delUri = clone $ro->uri;
        $delUri->query = $getQuery;


        // delete data in repository
        $this->repository->purge($delUri);


        // GET for re-generate (in interceptor)
        $ro->uri->query = $getQuery;
        $get = [$ro, 'onGet'];
        if (is_callable($get)) {
            \call_user_func_array($get, array_values($getQuery));
        }
    }

$this->getQuery($ro) も同クラス内ですが、こちらはリソースオブジェクトに刺さっているAbstractUriからクエリを作ります。それで、一般的にHTTPリクエストは string として処理されているため、この getQuery($ro) に入っている値も基本的には(事前に型変換が行われていない場合)すべて string なのではないかと思います。

それで、このまま Sample::onGet(int $id) を呼び出すと、 RefreshSameCommand クラスが declare(strict_types=1); になっているため、TypeError が発生するものと思います。

対応方針の検討

以下の2つの方針が考えられると思います。

  1. RefreshSameCommanddeclare(strict_types=1) を外す
  2. RefreshSameCommand::getQuery() の処理中で、ReflectionParameter から読み取った型に合わせてパラメータをキャストする

個人的には、2 は不要な複雑性を呼び込むように見え、 1 のほうが妥当な修正ではないかと考えています。

Resolve cache dependencies

キャッシュの依存性解決

リソース/aがリソース/bに依存し、リソース/bはリソース/cに依存している場合、リソース/cのキャッシュを破壊した場合にリソース/aとリソース/bのキャッシュが破壊される

依存の表し方について

メソッド a) @Embedで表されたリソースの依存関係をキャッシュの依存関係にそのまま使う。
メソッド b) キャッシュ依存グラフを外部の設定ファイルに持つ
メソッド c) キャッシュ依存グラフ専用のアノテーションを持つ

キャッシュの破壊について

メソッド 1) 全てを再生成する
メソッド 2) リソース本体とリソースのEmbed部分を別に管理し、それぞれ再生成する(ドーナッツキャッシュ)

現在、#94 でa-1 を実装しています。

メソッド a) の仕組み

  • /c のEtagはc1
  • /bのEtagはb1、etag-depsが c1
  • /aのEtagはa1、etag-depsが b1 c1

/bが更新されると、以下のように変化する

  • /bのEtagはb2、etag-depsが c1
  • /aのEtagはa2、etag-depsが b2 c1

(以上、etag-depsは含まれるリソースのETagリスト)

Surrogate-Keyへの適用

上記のetag-depsはそのまま Surrogate-Keyヘッダーとして利用可能ではないだろうか?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.