0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SOCKET-MANAGERを使った常駐型アプリ開発の手引き<新規開発環境>

Posted at

はじめに

この環境では基本的なディレクトリ構成とライブラリしか入っていませんので、真っ新な状態から開発を始められます。
ランタイムライブラリ(RuntimeManager)を使った常駐型アプリのみの実装では、SocketManagerクラスを使う場合に比べてプロトコル部を作成する必要がなくなるので、より簡易的な実装になります。

ここでは、環境のインストール手順とphp workerコマンドを使った新規のクラスを生成するコマンドをご紹介します。

インストール

開発環境は、以下のコマンドでインストールできます。

新規開発環境のインストール
> composer create-project socket-manager/new-project <インストール先のディレクトリ名>

インストールが完了すると、以下のディレクトリ構成で展開されます。

開発環境プロジェクトのディレクトリ構成
/app
    /InitClass          初期化クラス用
    /UnitParameter      UNITパラメータクラス用
    /ProtocolUnits      プロトコルUNIT定義クラス用
    /CommandUnits       コマンドUNIT定義クラス用
    /MainClass          メイン処理クラス用
/logs                   ログ出力用
/setting                設定ファイル用

php workerコマンドを実行すると以下のようなUsageが表示されます。

Usage表示
> php worker

SOCKET-MANAGER Framework 1.16.0

Usage:
  command [arguments]

 main
  Empty...
 craft
  craft:init <初期化クラス名>                     初期化クラスの生成
  craft:parameter <UNITパラメータクラス名>        UNITパラメータクラスの生成
  craft:protocol <プロトコルUNIT定義のクラス名>   プロトコルUNIT定義のクラスとステータス名Enumの生成
  craft:command <コマンドUNIT定義のクラス名>      コマンドUNIT定義のクラスとキュー/ステータス名Enumの生成
  craft:main <メイン処理のクラス名>               メイン処理クラスの生成
  craft:setting <設定ファイル名>                  設定ファイルの生成
  craft:locale <メッセージファイル名>             メッセージファイルの生成
 runtime
  runtime:init <初期化クラス名>                   初期化クラスの生成
  runtime:parameter <UNITパラメータクラス名>      UNITパラメータクラスの生成
  runtime:units <ランタイムUNIT定義のクラス名>    ランタイムUNIT定義のクラスとキュー/ステータス名Enumの生成
  runtime:main <メイン処理のクラス名>             メイン処理クラスの生成

laravel:commandコマンドに関してはLaravel環境でしか表示されません。

それでは動作確認のため、以下のコマンドを実行してメイン処理クラスを作成します。
今回はMainForTestという名前で作成します。

以下のように表示されれば成功です。

MainForTestクラス作成
> php worker runtime:main MainForTest

[success] メイン処理クラスの生成に成功しました (MainForTest)

再度php workerを実行してみます。

Usage表示
> php worker

SOCKET-MANAGER Framework 1.16.0

Usage:
  command [arguments]

 main
  app:main-for-test                              Command description
 craft
  craft:init <初期化クラス名>                     初期化クラスの生成
  craft:parameter <UNITパラメータクラス名>        UNITパラメータクラスの生成
  craft:protocol <プロトコルUNIT定義のクラス名>   プロトコルUNIT定義のクラスとステータス名Enumの生成
  craft:command <コマンドUNIT定義のクラス名>      コマンドUNIT定義のクラスとキュー/ステータス名Enumの生成
  craft:main <メイン処理のクラス名>               メイン処理クラスの生成
  craft:setting <設定ファイル名>                  設定ファイルの生成
  craft:locale <メッセージファイル名>             メッセージファイルの生成
 runtime
  runtime:init <初期化クラス名>                   初期化クラスの生成
  runtime:parameter <UNITパラメータクラス名>      UNITパラメータクラスの生成
  runtime:units <ランタイムUNIT定義のクラス名>    ランタイムUNIT定義のクラスとキュー/ステータス名Enumの生成
  runtime:main <メイン処理のクラス名>             メイン処理クラスの生成

アプリ名main-for-testという名前で登録されている事が確認できれば正常にインストールされています。

初期化クラスの実装

初期化クラスのソースは以下のコマンドで作成できます。
InitForTestという名前で作成する場合、以下のように表示されれば成功です。

初期化クラスの作成
> php worker runtime:init InitForTest

[success] 初期化クラスの生成に成功しました (InitForTest)
生成されるファイル
/app
    /InitClass
        InitForTest.php
生成される初期化クラスの内容
/**
 * RuntimeManager初期化クラス
 * 
 * IInitRuntimeManagerインタフェースをインプリメントする
 */
class InitForTest implements IInitRuntimeManager
{
    /**
     * コンストラクタ
     * 
     */
    public function __construct()
    {
    }

    /**
     * ログライターの取得
     * 
     * nullを返す場合は無効化(但し、ライブラリ内部で出力されているエラーメッセージも出力されない)
     * 
     * @return mixed "function(string $p_level, array $p_param): void" or null(ログ出力なし)
     */
    public function getLogWriter()
    {
        return null;
    }

    /**
     * 緊急停止時のコールバックの取得
     * 
     * 例外等の緊急停止時に実行される。nullを返す場合は無効化となる。
     * 
     * @return mixed "function(RuntimeManagerParameter $p_param)"
     */
    public function getEmergencyCallback()
    {
        return null;
    }

    /**
     * UNITパラメータインスタンスの取得
     * 
     * nullの場合はRuntimeManagerParameterのインスタンスが適用される
     * 
     * @return ?RuntimeManagerParameter RuntimeManagerParameterクラスのインスタンス(※1)
     * @see:RETURN (※1)当該クラス、あるいは当該クラスを継承したクラスも指定可
     */
    public function getUnitParameter(): ?RuntimeManagerParameter
    {
        return new RuntimeManagerParameter();
    }
}

ここでは以下の IInitRuntimeManager インターフェースメソッドを実装します。
各々のメソッドではnullを返す事で無効化できます。

■getLogWriterメソッドの実装
ライブラリ内でのログ出力に利用。
ハンドラーにする事でerror_log関数やフレームワークのLogger等の利用が可能。
■getEmergencyCallbackメソッドの実装
ステータスUNITで例外発生時に処理すべき内容がコールされる。
■getUnitParameterメソッドの実装
UNITパラメータとして利用される。グローバルエリアの管理が必要ないのであればRuntimeManagerParameterクラスをそのまま使っても構わない。

初期化クラスの実装内容の詳細については、以下のページをご覧ください。

ランタイムUNITクラスの実装

このクラスは以下のコマンドで作成できます。
RuntimeForTestという名前で作成する場合、以下のように表示されれば成功です。

ランタイムUNITクラスの作成
> php worker runtime:units RuntimeForTest

[success] ランタイムUNITクラスの生成に成功しました (RuntimeForTest)
[success] ランタイムUNITのキュー名Enumの生成に成功しました (RuntimeForTestQueueEnum)
[success] ランタイムUNITのステータス名Enumの生成に成功しました (RuntimeForTestStatusEnum)
生成されるファイル
/app
    /RuntimeUnits
        RuntimeForTest.php
        RuntimeForTestQueueEnum.php
        RuntimeForTestStatusEnum.php
生成されるランタイムUNITクラスの内容
/**
 * ランタイムUNIT登録クラス
 * 
 * IEntryUnitsインタフェースをインプリメントする
 */
class RuntimeForTest implements IEntryUnits
{
    /**
     * @var const QUEUE_LIST キュー名のリスト
     */
    protected const QUEUE_LIST = [
        RuntimeForTestQueueEnum::STARTUP->value     // 起動処理のキュー
    ];


    /**
     * コンストラクタ
     * 
     */
    public function __construct()
    {
    }

    /**
     * キューリストの取得
     * 
     * @return array キュー名のリスト
     */
    public function getQueueList(): array
    {
        return (array)static::QUEUE_LIST;
    }

    /**
     * ステータスUNITリストの取得
     * 
     * @param string $p_que キュー名
     * @return array キュー名に対応するUNITリスト
     */
    public function getUnitList(string $p_que): array
    {
        $ret = [];

        if($p_que === RuntimeForTestQueueEnum::STARTUP->value)
        {
            $ret[] = [
                'status' => RuntimeForTestStatusEnum::START->value,
                'unit' => $this->getStartupStart()
            ];
        }

        return $ret;
    }


    /**
     * 以降はステータスUNITの定義("STARTUP"キュー)
     */

    /**
     * ステータス名: START
     * 
     * 処理名:起動処理開始
     * 
     * @param RuntimeManagerParameter $p_param UNITパラメータ
     * @return ?string 遷移先のステータス名
     */
    protected function getStartupStart()
    {
        return function(RuntimeManagerParameter $p_param): ?string
        {
            $p_param->logWriter('debug', ['STARTUP' => 'START']);

            return null;
        };
    }

}

ここでは以下の IEntryUnits インターフェースメソッドを実装します。

■getQueueListメソッドの実装
ランタイムUNITクラスで利用するキューのリストを返す
■getUnitListメソッドの実装
引数のキュー名に対応するUNITのリストを返す
■各UNITの実装
getUnitListメソッドで返している定義済みのUNIT処理を実装

UNIT本体の処理は上記の場合getStartupStartメソッドでクロージャとして返していますが、グローバル関数名を指定する事も可能です。

ランタイムUNITクラスで利用するキュー名はライブラリ側のRuntimeQueueEnumクラスで予約されています。

ランタイムUNITクラスでの予約済Enum定義:RuntimeQueueEnum.php
enum RuntimeQueueEnum: string
{
    /**
     * @var 起動時のキュー名
     */
    case STARTUP = 'startup';
}

ランタイムUNITクラスの実装内容の詳細については、以下のページをご覧ください。

予約済ステータス

予約されているものは以下ライブラリ側のEnum定義のみです。

予約済Enum定義:StatusEnum.php
enum StatusEnum: string
{
    /**
     * @var UNITの処理開始時のステータス名
     */
    case START = 'start';
}

UNITパラメータクラスの実装

UNITパラメータクラスのソースは以下のコマンドで作成できます。
ParameterForTestという名前で作成する場合、以下のように表示されれば成功です。

UNITパラメータクラスの作成
> php worker runtime:parameter ParameterForTest

[success] UNITパラメータクラスの生成に成功しました (ParameterForTest)
生成されるファイル
/app
    /UnitParameter
        ParameterForTest.php

ここで述べているUNITパラメータというのはランタイムUNITで定義されているUNITの引数の部分です。

上記のランタイムUNITの例でいえばRuntimeManagerParameter $p_paramの部分になります。
この引数にはRuntimeManagerParameterクラスを継承しているものであれば何を指定しても構いません。

グローバルエリアを使う必要がなければ特に実装する事は何もありませんが、新規で作成した場合は以下のようにUNIT処理の引数の部分を必要に応じて置き替えてください。

修正前:ランタイムUNITクラス内のデフォルト
protected function getStartupStart()
{
    return function(RuntimeManagerParameter $p_param): ?string
    {
        $p_param->logWriter('debug', ['STARTUP' => 'START']);

        return null;
    };
}
修正後:新規で作成したクラス(ParameterForTest)で置き換え
protected function getStartupStart()
{
    return function(ParameterForTest $p_param): ?string
    {
        $p_param->logWriter('debug', ['STARTUP' => 'START']);

        return null;
    };
}

UNITパラメータクラスの実装内容の詳細については以下のページをご覧ください。

メイン処理クラスの実装

メイン処理クラスのソースは以下のコマンドで作成できます。
MainForTestという名前で作成する場合、以下のように表示されれば成功です。

メイン処理クラスの作成
> php worker runtime:main MainForTest

[success] メイン処理クラスの生成に成功しました (MainForTest)
生成されるファイル
/app
    /MainClass
        MainForTest.php

生成されるソースは次の通り。

app/MainClass/MainForTest.php
class MainForTest extends Console
{
    /**
     * @var string $identifer アプリケーション識別子
     */
    protected string $identifer = 'app:main-for-test';

    /**
     * @var string $description コマンド説明
     */
    protected string $description = 'Command description';


    /**
     * アプリケーション起動
     * 
     */
    public function exec()
    {
        // ランタイムマネージャーのインスタンス設定
        $manager_runtime = new RuntimeManager();

        /***********************************************************************
         * ランタイムマネージャーの初期設定
         * 
         * ランタイムUNITクラス等のインスタンスをここで設定します
         **********************************************************************/

        /**
         * 初期化クラスの設定
         * 
         * $manager_runtime->setInitRuntimeManager()メソッドで初期化クラスを設定します
         */

        /**
         * ランタイムUNITの設定
         * 
         * $manager_runtime->setRuntimeUnits()メソッドでランタイムUNITクラスを設定します
         */

        /***********************************************************************
         * ランタイムマネージャーの実行
         * 
         * 周期ドリブン処理を実行します
         **********************************************************************/

        // ノンブロッキングループ
        while(true)
        {
            // 周期ドリブン
            $ret = $manager_runtime->cycleDriven();
            if($ret === false)
            {
                goto finish;
            }
        }

finish:
        return;
    }
}

ここで実装が必要になるのは初期設定ブロックである以下の2点になります。

■初期化クラスの設定
初期化クラスのインスタンスを生成し、RuntimeManagerクラスのsetInitRuntimeManagerメソッドにインスタンスを引き渡す
■ランタイムUNITの設定
ランタイムUNITクラスのインスタンスを生成し、RuntimeManagerクラスのsetRuntimeUnitsメソッドにインスタンスを引き渡す

メイン処理クラスの実装内容の詳細については、以下のページをご覧ください。

設定ファイルの作成

設定ファイルは以下のコマンドで作成できます。
testという名前で作成する場合、以下のように表示されれば成功です。

設定ファイルの作成
> php worker craft:setting test

[success] 設定ファイルの生成に成功しました (test)
生成されるファイル
/setting
    test.php

作成されるソースは次の通り、空の配列のリターン値になります。

setting/test.php
return [

];

使い方

設定ファイル内の設定値を取得するヘルパー関数はLaravelと同様に使えるようにしています。

ここではtest_keyという名前の設定名を使って値を取得する場合を例に挙げます。

設定ファイルで以下のように連想配列を定義していたとします。

setting/test.php
return [
    'test_key' => 100
];

あとはプログラムの方でconfigヘルパー関数を使って以下のように取得するだけです。

configヘルパー関数で値を取得
$value = config('test.test_key', null);

変数$valueには100を返します。
関数の第一引数にはファイル名を含めたキー名をピリオド区切りで指定します。第二引数には値が取得できなかった場合のデフォルト値を指定します。

メッセージファイルの作成

メッセージ管理のコマンドはsetting/app.php内のlocale設定項目と連動します。
例えばlocaleの項目がjaの場合の挙動は以下の通りです。

メッセージファイルの作成
> php worker craft:locale test

[success] メッセージファイルの生成に成功しました (test)
生成されるファイル
/locale
    /ja
        test.php

test.phpのファイルはjaのサブディレクトリに格納されます。
作成されるソースは次の通り、空の配列のリターン値になります。

locale/ja/test.php
return [

];

使い方

メッセージファイル内のメッセージを取得するヘルパー関数はLaravelと同様に使えるようにしています。

ここではtest_keyという名前の設定名を使って値を取得する場合を例に挙げます。

メッセージファイルで以下のように連想配列を定義していたとします。

locale/ja/test.php
return [
    'test_key' => 'テストメッセージ'
];

あとはプログラムの方で__ヘルパー関数を使って以下のように取得するだけです。

__ヘルパー関数でメッセージを取得
$value = __('test.test_key');

変数$valueには「テストメッセージ」という文字列を返します。

また、以下のようにプレースホルダも使えます。

locale/ja/test.php
return [
    'test_key' => '私の名前は:nameです。年齢は:age歳です。'
];
プレースホルダを使ってメッセージを取得
$value = __('test.test_key', ['name' => '山田太郎', 'age' => 20]);

変数$valueには「私の名前は山田太郎です。年齢は20歳です。」という文字列を返します。

おわりに

動作確認をしながら進めるのであれば以下の順に進めるのがいいでしょう。

1.初期化クラスの実装
2.メイン処理クラスの実装
3.ランタイムUNITクラスの実装

初期化クラスを実装後は、ログライターの出力形式や緊急停止時の処理が変わらない限り、触る事はほとんどないでしょう。

そしてランタイムUNITのクラスは初期状態のままでいいのでメイン処理クラスで設定だけ済ませておいた上でランタイムUNITを作成するたびに動作確認していくのが順当かと思われます。

UNITパラメータクラスの方はUNIT処理の作成中にグローバルエリアの管理が必要になった時に実装を進める形でいいでしょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?