Search by

ryunosuke / hellowo

arima-ryunosuke

simple job worker

v1.2.11 2026-10-05 04:47 UTC

README

Description

This package is simple job worker.

Install

{
    "require": {
        "ryunosuke/hellowo": "dev-master"
    }
}

This requires pcntl extension. Also, Windows only works minimally.

Feature

Driver

Driver features:

Driver FileSystem Gearman Beanstalk MySql PostgreSql
simply very high high high middle middle
pull or push(*1) pull/push(inotify) push push pull/push(trigger) pull/push(pub/sub)
multi worker server optional(*2) yes yes yes yes
heartbeat other server(*3) no no no yes (kill) yes (pg_terminate_backend)
not lost to sudden death yes (flock) no yes (ttr) yes (FOR UPDATE) yes (FOR UPDATE)
priority job yes yes yes yes yes
delay job yes no yes yes yes
managed retry no no yes no no
unmanaged retry limit yes no no yes yes
clustering no no no optional(*4) optional(*4)
  • *1 push is almost real-time, but pull has time lag due to polling
  • *2 e.g. NFS
  • *3 Except for FileSystem, TCP keepalive can be enabled to some extent
  • *4 e.g. Replication, Fabric, NDB

Worker

The recommended process manager is systemd.

work mode

The basic operation is in series. If you want to run multiple jobs in parallel, you need to launch multiple processes. This can be easily achieved using systemd's service-template+target feature.

Each process is completely independent, simple, and highly robust, but it uses high memory usage.

fork mode

It will fork internally as needed. The forked processes will run in parallel. You can simply use type=simple with systemd.

Although it is complex and the various processes work in coordination, but it uses low memory usage.

common

SIGALRM is used to implement the timeout, so it cannot be used by the user. When it receives an SIGTERM or SIGINT, it waits for the currently running job until stopping it. Therefore, in some cases, it may take a long time to stop (see TimeoutStopSec of systemd).

Default logging, operation log is written to STDOUT. php error log is written to STDERR. Operation log can be changed by overriding the logger option. php error log uses system default. This can be changed by php.ini or ini_set.

polling

FileSystem, MySql, PostgreSql are support below polling mode:

mode signal file socket sql(mysql only)
sleep call sleep syscall select local pipe listen UDP socket call SLEEP sql function
awake receive USR1 write to local pipe send to UDP socket kill query
simply high middle middle low
versatility low middle high low
systemd no yes yes yes
inter server no no yes yes
sharing

MySql, PostgreSql are support sharing mode.

Polling executes SELECT statements fired off repeatedly for as many times as there are workers, but Sharing caches in local the results of the SELECT statement.

not sharing:

graph TD
    subgraph Workers["Workers"]
        P1["Worker1"]
        P2["Worker2"]
        P3["Worker3"]
    end

    P1 & P2 & P3 -->|"SELECT job(per poll second)"| Database
Loading

sharing:

graph TD
    subgraph Workers["Workers"]
        P1["Worker1"]
        P2["Worker2"]
        P3["Worker3"]
    end

    P1 & P2 & P3 -->|"read"| LocalCache
    LocalCache -->|"SELECT job(per poll second)"| Database
Loading
lookahead

FileSystem, MySql, PostgreSql are support lookahead mode.

Polling inevitably causes delays (especially when dealing with future times), but Lookahead prefetchs future job within lookahead seconds.

e.g.

  • NOW: 2014-12:24 12:34:56
  • jobA: 2014-12:24 13:00:00
  • jobB: 2014-12:24 12:35:00

jobA is not prefetched, but jobB is prefetched and next sleep time is set 4 second(12:35:00 - 12:34:56). so jobB run exactly on time.

heartbeat

MySql, PostgreSql are support heartbeat mode.

sequenceDiagram
    autonumber

    participant Active as Workers(active)
    participant Database
    participant Dead as Workers(dead)

    rect rgb(222, 255, 222)
        Active->>Database: require PROCESS LIST
        Database->>Active: return PROCESS LIST
    end

    rect rgb(255, 255, 0)
        Active->>Dead: ping
        Dead-->>Active: pong
    end

    alt Timeout
        rect rgb(255, 222, 222)
            Active->>Database: execute KILL
            Dead--xDatabase: KILL
        end
    end
Loading

This is bad practice; if TCP keepalive is available, you should use that instead.

Client

Client is a simple class from which only the request part of the driver is extracted. You can use send or sendBulk for add job.

Demo

  • Driver: mysql
  • Parallel: 4-8
  • Log: /var/log/hellowo
sudo sh demo/install.sh
sudo systemctl restart hellowo
php demo/client.php 100

execution log

cat /var/log/hellowo/stdout.log
[Y-m-dTH:i:s.v][1045984] ...
[Y-m-dTH:i:s.v][1045984] ...
[Y-m-dTH:i:s.v][1045984] ...

receive data

cat -n /var/log/hellowo/receive.log
     1  data-0017
     2  data-0001
     3  data-0005
     4  data-0021
     5  data-0010
    ...
    95  data-0087
    96  data-0092
    97  data-0089
    98  data-0098
    99  data-0100
   100  data-0099

License

MIT

Release

Versioning is romantic versioning(no semantic versioning).

  • major: large BC break. e.g. change architecture, package, class etc
  • minor: small BC break. e.g. change arguments, return type etc
  • patch: no BC break. e.g. fix bug, add optional arguments, code format etc

x.y.z

  • API の除去
    • protected で不要なメソッドを隠す意図の設計だったが足枷になってきている

1.2.11

  • [feature] Amazon Aurora 対応
  • [refactor] トリガー廃止の布石
  • [refactor] 完了後に unshare するのではなく、事前に unshare する
  • [refactor] ポーリングの通知方法を変更
  • [feature] socket の出力を待つ socket wait mode を追加
  • [feature] 通知が来たら sharedJob をクリアする機能の改善
  • [feature] PDODriver の追加
  • [refactor] driver の機能を trait に分離
  • [feature] restartClosure のリッチ化
  • [feature] プロセス名やログの強化
  • [feature] 自動通知の最大制限設定を追加
  • [feature] FileSystemDriver の即死リカバリ対応(ttr 廃止)
  • [feature] sleep(シグナル待ち)ではなく pipe の出力を待つ file wait mode を追加
  • [feature] 通知が来たら sharedJob をクリアする機能
  • [feature] 2件以上のジョブが見つかったら通知して巻き込む機能
  • [feature] fork モードでも starttime 設定を活かす
  • [feature] ジョブの先読み機能
  • [feature] driver に id を追加
  • [fixbug] daemonize にあるべき処理が setup にあった不具合
  • [fixbug] 子プロセスのメッセージを取りこぼす不具合
  • [fixbug] close しても close しきれないことがある不具合
  • [fixbug] DB 系ドライバでトランザクション内の notify が効いていない不具合
  • [fixbug] error を同一テーブルに保持してる場合に list にも含まれてくる不具合
  • [change] テーブル定義部分を変更
  • [chore] 細かいところ修正

1.2.10

  • [refactor] inspection 修正
  • [feature] Throwable(Error) の特別扱いを廃止

1.2.9

  • [feature] mysql の wait_timeout を指定する機能
  • [feature] ログの強化
  • [change] 増えたプロセス優先で殺す仕様を撤廃

1.2.8

  • Merge tag 'v1.1.13'
    • register_shutdown_function の件は攻めすぎたので deprecated

1.2.7

  • [fixbug] deadmode を設定していないと無限リトライする不具合

1.2.6

  • [change] 例外キャッチ時の sleep を設定
  • [feature] systemctl status でリソースや統計が見える機能
  • [refactor] limit 指定で同じ数字を2回書くのを修正
  • [refactor] posix::pgrep を Generator 化

1.2.5

  • [feature] driver にも logger を持たせる
  • [feature] ジョブが連なっているときは wait しない
  • [refactor] posix::pgrep をリライト
  • [refactor] notifyLocal とプロセス名の関係をリワーク
  • [change] interpolate で階層のないリスト配列を特別扱いする
  • [change] psr-3 的に exception というキーに例外オブジェクト以外を与えてはならない
  • [feature] restart を fork でも活かす

1.2.4

  • [feature] fork モードを仮実装
  • [feature] transaction を外だし
  • [feature] register_shutdown_function を模倣する機能
  • [feature] client/worker が共通コネクションの driver の遅延接続
  • [feature] continue/breather の正規化
  • [feature] restart の引数に workload(処理回数) を追加
  • [feature] ログ回りの改善

1.2.3

  • Merge tag 'v1.1.12'

1.2.2

  • Merge tag 'v1.1.11'

1.2.1

  • [fixbug] client で文字列以外を send するときに IDE エラーが出る

1.2.0

  • [fixbug] gearman に未来 job を登録するとその間無限ループする
  • [*feature] job 側にも timeout を持たせる
  • [*feature] delay に予定時刻を入れられる機能
  • [*feature] 失敗したジョブを保存する機能
  • [feature] sendBulk を追加
  • [*change] sendJson 廃止
  • [*change] notify は Client の責務とする
  • [*change] job データは json で包む
  • [*change] wait 系のデフォルト waittime を 10 に変更
  • [*change] drop deprecated
  • [tests] 意味の分からないコードがあったので除去

1.1.13

  • [fixbug] 異常終了時に当該ジョブを実行し続けてしまう
  • [feature] list メソッドを追加

1.1.12

  • [feature] 絶え間なくジョブが実行され続けたら警告を出す
  • [feature] 結果の如何にかかわらず job を検知して終了した場合のイベント finish を追加

1.1.11

  • [change] ブランチ切り替えがしんどいので docker-compose の変更をバックポート
  • [feature] standup イベントを追加
  • [fixbug] readonly 状態では SELECT FOR UPDATE を投げられない
  • [fixbug] エラー時は正常終了ではなく異常終了で systemd の再起動を促す

1.1.10

  • [feature] breather イベントを追加
  • [change] rework Gearman
  • [feature] cancel 実装
  • [refactor] 例外の構造変更と UnsupportedException を追加
  • [fixbug] sha1 は無駄だし一意ではない

1.1.9

  • [feature] prepare は1回で十分
  • [fixbug] systemd で起動しない不具合
  • [fixbug] EchoLogger の引数漏れ

1.1.8

  • [feature] EchoLogger にレベルフィルタを実装
  • [feature] ジョブ候補をファイルキャッシュする機能
  • [feature] ジョブを分散させるために starttime を追加
  • [fixbug] 無駄な行を取りすぎている
  • [fixbug] active 側で isStandby が高頻度で呼ばれている

1.1.7

  • [fixbug] 並列数が1になることがある不具合

1.1.6

  • [feature] start 時に work を与えられる機能

1.1.5

  • [feature] PostgreSqlDriver
  • [fixbug] 初回実行時に setup されない不具合
  • [fixbug] 一部のドライバーにミリ秒を与えるとエラーになる
  • [fixbug] heartbeat 秒応答がないホストに対して heartbeat 秒 ping を待機している
  • [feature] delay がある場合は notify しても無駄
  • [feature] MySql のミリ秒対応

1.1.4

  • [fixbug] USR1 以外でも async をキャンセルしていた
  • [fixbug] select と sleep で使用されるインデックスが異なる可能性がある

1.1.3

  • [feature] JSON を組み込みで実装
  • [refactor] API の整理
  • [refactor] ext のパスを変更
  • [refactor] Listener の階層を Logger と合わせる

1.1.2

  • [feature] リトライ回数を実装
  • [fixbug] standby 状態で setup して死ぬ不具合を修正

1.1.1

  • [feature] added restart trigger

1.1.0

  • [*change] select+done+retry -> generator
  • [change] log format
  • [fixbug] no keeps connecting on server gone away

1.0.1

  • [feature] check writable mode
  • [fixbug] transaction may not be closed
  • [fixbug] fix miss (PROCEDURE -> FUNCTION)

1.0.0

  • [feature] added logger logs when Throwable
  • [refactor] changed nullable to notnull

0.2.0

  • [fixbug] fixed "Commands out of sync" when receive USR1
  • [fixbug] deleted IF EXISTS from mysql driver
  • [feature] added listen cycle event

0.1.0

  • [change] move notify to notifyLocal

0.0.0

  • publish