AsyncJobsDB.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. /**
  3. *
  4. `CRM_ASYNC_JOB_LOG`:
  5. `ID`
  6. `ID_FUNCTION`
  7. `ID_SOURCE_JOB`
  8. `P_ID`
  9. `DATE`
  10. `VERSION`
  11. `JOB_NAME`
  12. `LOCK_VALUE`
  13. `USER`
  14. `A_STATUS`: default 'WAITING' - not started, 'NORMAL' - started, 'OFF_HARD' - not running, 'DELETED' - removed
  15. `A_RECORD_CREATE_DATE`
  16. `A_RECORD_CREATE_AUTHOR`
  17. `A_RECORD_UPDATE_DATE`
  18. `A_RECORD_UPDATE_AUTHOR`
  19. *
  20. *
  21. */
  22. Lib::loadClass('Request');
  23. class Core_AsyncJobsDB {
  24. static $VERSION = 1; // `CRM_CONFIG`.`CONF_KEY` = 'Core_AsyncJobs__version'
  25. static $CRM_CONFIG_VERSION_KEY = 'Core_AsyncJobs__version';
  26. static function insert($item) {
  27. if (empty($item['JOB_NAME'])) throw new Exception("Missing JOB_NAME in Core_AsyncJobsDB::insert");
  28. return DB::getPDO()->insert('CRM_ASYNC_JOB_LOG', array_merge([
  29. 'ID_FUNCTION' => 0, // int(11) NOT NULL,
  30. // 'ID_SOURCE_JOB' int(11) NOT NULL DEFAULT 0, -- id job
  31. // 'P_ID' int(11) NOT NULL DEFAULT 0, -- parent job id
  32. 'DATE' => date("Y-m-d"),// date NOT NULL,
  33. // 'VERSION' => 0, // int(11) NOT NULL DEFAULT 0,
  34. 'JOB_NAME' => '', // varchar(200) NOT NULL, -- copy from CRM_ASYNC_FUNCTIONS
  35. 'LOCK_VALUE' => '', // varchar(200) NOT NULL DEFAULT '', -- second part for unique JOB_NAME eg. primaryKey
  36. 'USER' => User::getLogin(), // varchar(20) NOT NULL, -- user who start this function
  37. 'A_STATUS' => 'WAITING',
  38. 'A_RECORD_CREATE_DATE' => "NOW()",
  39. 'A_RECORD_CREATE_AUTHOR' => User::getLogin(),
  40. // UNIQUE KEY 'JOB_LOCK' ('JOB_NAME', 'LOCK_VALUE', 'USER'), -- add USER to store user click and respond that job is running by other user
  41. // KEY 'DATE' ('DATE'),
  42. // KEY 'A_STATUS' ('A_STATUS'),
  43. // KEY 'A_RECORD_UPDATE_DATE' ('A_RECORD_UPDATE_DATE')
  44. ], $item));
  45. }
  46. static function fetch($idJob) {
  47. return DB::getPDO()->fetchFirst("
  48. select j.*
  49. from CRM_ASYNC_JOB_LOG j
  50. where j.ID = :id
  51. ", [
  52. ':id' => $idJob,
  53. ]);
  54. }
  55. static function updateStatus($idJob, $status, $item = []) {
  56. if ($item) $item = self::fetch($idJob);
  57. if ($status != $item['A_STATUS']) {
  58. DB::getPDO()->update('CRM_ASYNC_JOB_LOG', 'ID', $idJob, [
  59. 'A_STATUS' => $status,
  60. ]);
  61. // TODO: _HIST
  62. }
  63. }
  64. static function checkAsyncJobDatabase() {
  65. // `CRM_CONFIG`.`CONF_KEY` = 'Core_AsyncJobs__version'
  66. $dbVersion = (int)DB::getPDO()->fetchValue(" select CONF_VAL from CRM_CONFIG where CONF_KEY = :key ", [ ':key' => self::$CRM_CONFIG_VERSION_KEY ]);
  67. if ($dbVersion < 1) self::upgradeAsyncJobDatabaseToVersion1();
  68. // $dbVersion = (int)DB::getPDO()->fetchValue(" select CONF_VAL from CRM_CONFIG where CONF_KEY = :key ", [ ':key' => 'Core_AsyncJobs__version' ]);
  69. // if ($dbVersion < 2) self::upgradeAsyncJobDatabaseToVersion2();
  70. $dbVersion = (int)DB::getPDO()->fetchValue(" select CONF_VAL from CRM_CONFIG where CONF_KEY = :key ", [ ':key' => self::$CRM_CONFIG_VERSION_KEY ]);
  71. return ($dbVersion < self::$VERSION) ? false : true;
  72. }
  73. static function upgradeAsyncJobDatabaseToVersion1() {
  74. // - insertOrUpdate new row in `CRM_ASYNC_FUNCTIONS` ( $TODAY, $version, $user, $jobName )
  75. // - $JOB_ID = fetchValue select ID from `CRM_ASYNC_FUNCTIONS` where JOB_NAME = $jobName
  76. // - `CRM_ASYNC_FUNCTIONS`.`A_STATUS` default 'WAITING' - not started
  77. // - `CRM_ASYNC_FUNCTIONS`.`A_STATUS`: 'NORMAL' - started
  78. // - `CRM_ASYNC_FUNCTIONS`.`A_STATUS`: 'OFF_HARD' - not running
  79. // - `CRM_ASYNC_FUNCTIONS`.`A_STATUS`: 'DELETED' - removed
  80. $sql = "
  81. CREATE TABLE IF NOT EXISTS `CRM_ASYNC_FUNCTIONS` ( -- list of async function definitions / config
  82. `ID` int(11) NOT NULL AUTO_INCREMENT,
  83. `ID_ZASOB` int(11) NOT NULL DEFAULT 0, -- TODO - register function in CRM_LISTA_ZASOBOW URL_ACTION to set perms
  84. `JOB_NAME` varchar(200) NOT NULL,
  85. `VERSION` int(11) NOT NULL DEFAULT 0,
  86. `LOCK_TYPE` enum('ROW', 'TABLE', 'SYSTEM', 'NO_LOCK') DEFAULT 'ROW',
  87. -- ROW - only one active job per row, eg. create pdf, close FV, @require primaryKey in JOB.LOCK_VALUE
  88. -- TABLE - ony one active job per table, eg. update columns, make report, sync
  89. -- SYSTEM - only one active job
  90. -- TODO USER_... - lock per user
  91. -- NO_LOCK - allow multiple jobs
  92. -- `USER` varchar(20) NOT NULL,
  93. -- `DATE` date NOT NULL,
  94. -- `A_STATUS` enum('WAITING','NORMAL','WARNING','OFF_SOFT','OFF_HARD','DELETED') DEFAULT 'WAITING',
  95. `A_RECORD_CREATE_DATE` datetime NOT NULL,
  96. `A_RECORD_CREATE_AUTHOR` varchar(20) NOT NULL,
  97. `A_RECORD_UPDATE_DATE` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  98. `A_RECORD_UPDATE_AUTHOR` varchar(20) NOT NULL,
  99. PRIMARY KEY (`ID`),
  100. UNIQUE KEY `JOB_NAME` (`JOB_NAME`),
  101. KEY `DATE` (`DATE`),
  102. KEY `A_STATUS` (`A_STATUS`),
  103. KEY `A_RECORD_UPDATE_DATE` (`A_RECORD_UPDATE_DATE`)
  104. ) ENGINE=MyISAM DEFAULT CHARSET=latin2;
  105. ";
  106. // DB::getPDO()->execSql($sql);
  107. $sql = "
  108. CREATE TABLE IF NOT EXISTS `CRM_ASYNC_JOB_LOG` (
  109. `ID` int(11) NOT NULL AUTO_INCREMENT,
  110. `ID_FUNCTION` int(11) NOT NULL,
  111. `ID_SOURCE_JOB` int(11) NOT NULL DEFAULT 0, -- id job
  112. `P_ID` int(11) NOT NULL DEFAULT 0, -- parent job id
  113. `DATE` date NOT NULL,
  114. `VERSION` int(11) NOT NULL DEFAULT 0,
  115. `JOB_NAME` varchar(200) NOT NULL, -- copy from CRM_ASYNC_FUNCTIONS
  116. `LOCK_VALUE` varchar(200) NOT NULL DEFAULT '', -- second part for unique JOB_NAME eg. primaryKey
  117. `USER` varchar(20) NOT NULL, -- user who start this function
  118. `A_STATUS` enum('WAITING','NORMAL','WARNING','OFF_SOFT','OFF_HARD','DELETED') DEFAULT 'WAITING',
  119. `A_RECORD_CREATE_DATE` datetime NOT NULL,
  120. `A_RECORD_CREATE_AUTHOR` varchar(20) NOT NULL,
  121. `A_RECORD_UPDATE_DATE` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  122. `A_RECORD_UPDATE_AUTHOR` varchar(20) NOT NULL,
  123. PRIMARY KEY (`ID`),
  124. -- UNIQUE KEY `JOB_LOCK` (`JOB_NAME`, `LOCK_VALUE`, `USER`), -- add USER to store user click and respond that job is running by other user
  125. KEY `DATE` (`DATE`),
  126. KEY `A_STATUS` (`A_STATUS`),
  127. KEY `A_RECORD_UPDATE_DATE` (`A_RECORD_UPDATE_DATE`)
  128. ) ENGINE=MyISAM DEFAULT CHARSET=latin2;
  129. ";
  130. DB::getPDO()->execSql($sql);
  131. // @usage:
  132. // `CRM_ASYNC_FUNCTIONS`.`JOB_NAME` = '
  133. // route = ant
  134. // -- & path = default_db.in7_dziennik_koresp/test-bash
  135. // & template = test-loop
  136. // & typeName = default_db:IN7_DZIENNIK_KORESP
  137. // & primaryKey = 66263
  138. // & primaryKeyField = ID
  139. // -> `CRM_ASYNC_FUNCTIONS`.`JOB_NAME` =
  140. // namespace = default_db/IN7_DZIENNIK_KORESP
  141. // ant = test-bash
  142. // template = test-loop
  143. // primaryKey = 66263
  144. // -> `CRM_ASYNC_FUNCTIONS`.`JOB_NAME` Format: "{$type}|..."
  145. // -> `CRM_ASYNC_FUNCTIONS`.`JOB_NAME` Format: "Ant|{$namespace}"
  146. // -> `CRM_ASYNC_JOB_LOG`.`LOCK_VALUE` Format: "{$primaryKey}|{$func_name}|..."
  147. // -> `CRM_ASYNC_JOB_LOG`.`LOCK_VALUE` Format: "{$primaryKey}|{$func_name}|{$template}"
  148. // -> Example: JOB_NAME = 'Ant|default_db/IN7_DZIENNIK_KORESP', LOCK_VALUE = '66263|test-bash|test-loop'
  149. // Add fields:
  150. // - function config at execution time:
  151. // - eg LOCK by user | feature | namespace | no_lock -- should contain in name
  152. // - process result - last result - NO - result from file, separate request needed
  153. // IDEA: 2 tables:
  154. // - `Config` - for function config (create row if not exists)
  155. // - `Log` - for log where JOB_ID is created or used from Config table
  156. // then createNewJob:
  157. // 1. fetch job config from CRM_ASYNC_FUNCTIONS_CONFIG
  158. // 1.1 IF 404 then create row, read config from function (how?)
  159. // 1.2 IF exists then check status and lock config
  160. // 1.2.1 IF online and lock then return error
  161. // 1.2.2 IF !online and !lock then create new row in Log table and return correct JOB_ID
  162. self::_upgdateAsyncJobDatabaseVersion($version = 1);
  163. }
  164. static function upgradeAsyncJobDatabaseToVersion2() {
  165. // ...
  166. self::_upgdateAsyncJobDatabaseVersion($version = 2);
  167. }
  168. static function _upgdateAsyncJobDatabaseVersion($version) {
  169. DB::getPDO()->insertOrUpdate('CRM_CONFIG', [
  170. 'CONF_KEY' => self::$CRM_CONFIG_VERSION_KEY,
  171. '@insert' => [
  172. 'CONF_VAL' => $version,
  173. ],
  174. '@update' => [
  175. 'CONF_VAL' => $version,
  176. ]
  177. ]);
  178. }
  179. }