1+ <?php
2+ /**
3+ * Created by PhpStorm.
4+ * User: semenov
5+ * Date: 08.07.14
6+ * Time: 11:13
7+ */
8+
9+ namespace yii2mod \cron \behaviors ;
10+
11+ use yii \base \Behavior ;
12+ use yii \console \Controller ;
13+
14+
15+ /**
16+ * MutexConsoleCommandBehavior allows console command actions being run with mutex protection.
17+ *
18+ * Usage:
19+ * <code>
20+ * class MyCommand extends Controller
21+ * {
22+ * public function behaviors()
23+ * {
24+ * return array(
25+ * 'mutexBehavior' => array(
26+ * 'class' => 'yii2mod\cron\behaviors\MutexConsoleCommandBehavior',
27+ * 'mutexActions' => array('index'),
28+ * ),
29+ * );
30+ * }
31+ * }
32+ * </code>
33+ *
34+ * @method \Controller getOwner()
35+ *
36+ * @author Klimov Paul <klimov@zfort.com>
37+ * @author Dmitry Semenov <disemx@gmail.com>
38+ * @version $Id$
39+ * @package zfort\mutex\behavior
40+ * @since 1.0
41+ */
42+ class MutexConsoleCommandBehavior extends Behavior
43+ {
44+ /**
45+ * @var string name of the mutex application component.
46+ */
47+ public $ mutex = 'mutex ' ;
48+ /**
49+ * @var array list of action names, which mutex should be applied to.
50+ */
51+ public $ mutexActions = array ();
52+ /**
53+ * @var integer exit code, which should be returned by console command in case it
54+ * is terminated due to mutex lock.
55+ */
56+ public $ mutexExitCode = 100 ;
57+
58+ /**
59+ * @inheritdoc
60+ */
61+ public function events ()
62+ {
63+ return [
64+ Controller::EVENT_BEFORE_ACTION => 'beforeAction ' ,
65+ Controller::EVENT_AFTER_ACTION => 'afterAction ' ,
66+ ];
67+ }
68+
69+ /**
70+ * @return Mutex mutex application component instance.
71+ */
72+ public function getMutex ()
73+ {
74+ return \Yii::$ app ->get ($ this ->mutex );
75+ }
76+
77+ /**
78+ * Composes the mutex name.
79+ *
80+ * @param string $action command action name.
81+ *
82+ * @return string mutex name.
83+ */
84+ protected function composeMutexName ($ action )
85+ {
86+ return $ this ->getOwner ()->getName () . '- ' . $ action ;
87+ }
88+
89+ /**
90+ * Checks if specified action is among mutex actions.
91+ *
92+ * @param string $action action name.
93+ *
94+ * @return boolean whether action should be under mutex.
95+ */
96+ public function checkIsMutexAction ($ action )
97+ {
98+ return in_array (strtolower ($ action ), $ this ->mutexActions );
99+ }
100+
101+ /**
102+ * Responds to {@link CConsoleCommand::onBeforeAction} event.
103+ * Override this method and make it public if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
104+ *
105+ * @param CConsoleCommandEvent $event event parameter
106+ */
107+ public function beforeAction ($ event )
108+ {
109+ if ($ this ->checkIsMutexAction ($ event ->action )) {
110+ $ mutexName = $ this ->composeMutexName ($ event ->action );
111+ if (!$ this ->getMutex ()->acquire ($ mutexName )) {
112+ echo "Execution terminated: command is already running. \n" ;
113+ $ event ->stopCommand = true ;
114+ $ event ->exitCode = $ this ->mutexExitCode ;
115+ }
116+ }
117+ }
118+
119+ /**
120+ * Responds to {@link CConsoleCommand::onAfterAction} event.
121+ * Override this method and make it public if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
122+ *
123+ * @param CConsoleCommandEvent $event event parameter
124+ */
125+ public function afterAction ($ event )
126+ {
127+ if ($ this ->checkIsMutexAction ($ event ->action )) {
128+ $ mutexName = $ this ->composeMutexName ($ event ->action );
129+ $ this ->getMutex ()->release ($ mutexName );
130+ }
131+ }
132+ }
0 commit comments