Skip to content

Commit d549992

Browse files
committed
Update error handling
1 parent fd64498 commit d549992

5 files changed

Lines changed: 117 additions & 99 deletions

File tree

‎ProcessMaker/Jobs/ErrorHandling.php‎

Lines changed: 104 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace ProcessMaker\Jobs;
44

5+
use Illuminate\Support\Arr;
56
use Illuminate\Support\Facades\Log;
67
use Illuminate\Support\Facades\Notification;
78
use ProcessMaker\Models\Process;
@@ -12,15 +13,30 @@
1213

1314
class ErrorHandling
1415
{
15-
public $errorHandling = [];
16-
17-
public static $callback;
16+
/**
17+
* Error handling settings that are set in modeler.
18+
*
19+
* These settings take precedence over those set in script or
20+
* data source configuration.
21+
*
22+
* @var array
23+
*/
24+
public $bpmnErrorHandling = [];
25+
26+
/**
27+
* Default settings that are set in script or data source configuration.
28+
*
29+
* $bpmnErrorHandling takes precedence over these if set.
30+
*
31+
* @var array
32+
*/
33+
public $defaultErrorHandling = [];
1834

1935
public function __construct(
36+
public $element,
2037
public $processRequestToken,
21-
)
22-
{
23-
38+
) {
39+
$this->bpmnErrorHandling = json_decode($element->getProperty('errorHandling'), true) ?? [];
2440
}
2541

2642
public function handleRetries($job, $exception)
@@ -35,11 +51,9 @@ public function handleRetries($job, $exception)
3551
return $message;
3652
}
3753

38-
$message = __('Job failed after :attempts total attempts', ['attempts' => $job->attemptNum - 1]) . "\n" . $message;
54+
$message = __('Job failed after :attempts total attempts', ['attempts' => $job->attemptNum]) . "\n" . $message;
3955

4056
$this->sendExecutionErrorNotification($message);
41-
42-
return $message;
4357
} else {
4458
$this->sendExecutionErrorNotification($message);
4559
}
@@ -70,70 +84,114 @@ public function sendExecutionErrorNotification(string $message)
7084
$user = $this->processRequestToken->processRequest->processVersion->manager;
7185
if ($user !== null) {
7286
Log::info('Send Execution Error Notification: ' . $message);
73-
Notification::send($user, new ErrorExecutionNotification($this->processRequestToken, $message, $this->errorHandling));
87+
Notification::send($user, new ErrorExecutionNotification($this->processRequestToken, $message, $this->bpmnErrorHandling));
7488
}
7589
}
7690
}
7791

7892
/**
79-
* This sets the property errorHandling, and if the parameter doesn't exist,
80-
* it returns the current value of property errorHandling.
93+
* Get the effective timeout
8194
*
82-
* @param mixed $value
83-
* @return mixed
95+
* @return int
8496
*/
85-
public function errorHandling($value = null)
97+
public function timeout()
8698
{
87-
Log::info('Setting errorHandling', ['value' => $value]);
88-
if (is_array($value) && !empty($value)) {
89-
$array = [
90-
'timeout',
91-
'retry_attempts',
92-
'retry_wait_time',
93-
];
94-
foreach ($array as $val) {
95-
$digit = 0;
96-
if (is_string($value[$val]) && ctype_digit($value[$val])) {
97-
$digit = intval($value[$val]);
98-
}
99-
if (is_int($value[$val])) {
100-
$digit = $value[$val];
101-
}
102-
$value[$val] = $digit;
103-
}
104-
$this->errorHandling = $value;
105-
}
106-
107-
return $this->errorHandling;
99+
return $this->get('timeout');
108100
}
109101

110102
/**
111-
* This retrieves the value of errorHandling['timeout'].
103+
* Get the effective retry attempts
112104
*
113105
* @return int
114106
*/
115-
public function timeout()
107+
public function retryAttempts()
116108
{
117-
return $this->errorHandling['timeout'];
109+
return $this->get('retry_attempts');
118110
}
119111

120112
/**
121-
* This retrieves the value of errorHandling['retry_attempts'].
113+
* Get the effective retry wait time.
122114
*
123115
* @return int
124116
*/
125-
public function retryAttempts()
117+
public function retryWaitTime()
126118
{
127-
return $this->errorHandling['retry_attempts'];
119+
return $this->get('retry_wait_time');
128120
}
129121

130122
/**
131-
* This retrieves the value of errorHandling['retry_wait_time'].
123+
* Get the attribute from the bpmnErrorHandling array but if it's not set
124+
* return the defaultErrorHandling value
132125
*
133-
* @return int
126+
* @param string $attribute
127+
* @return void
134128
*/
135-
public function retryWaitTime()
129+
public function get($attribute)
130+
{
131+
$value = Arr::get(
132+
$this->bpmnErrorHandling,
133+
$attribute,
134+
null
135+
);
136+
137+
if ($value === null || $value === '') {
138+
$value = Arr::get($this->defaultErrorHandling, $attribute, 0);
139+
}
140+
141+
return (int) $value;
142+
}
143+
144+
/**
145+
* Set defaults from script model
146+
*
147+
* @param ScriptVersion $script
148+
* @return void
149+
*/
150+
public function setDefaultsFromScript(ScriptVersion $script)
136151
{
137-
return $this->errorHandling['retry_wait_time'];
152+
$this->defaultErrorHandling = [
153+
'timeout' => $script->timeout,
154+
'retry_attempts' => $script->retry_attempts,
155+
'retry_wait_time' => $script->retry_wait_time,
156+
];
157+
}
158+
159+
/**
160+
* Set defaults from data source model endpoint
161+
*
162+
* @param array $config
163+
* @return void
164+
*/
165+
public function setDefaultsFromDataSourceConfig(array $config)
166+
{
167+
// If this is not a Data Connecter, don't do any error handling
168+
$id = Arr::get($config, 'dataSource', null);
169+
if (!$id) {
170+
return;
171+
}
172+
173+
// Check if the data source package is installed
174+
$class = "ProcessMaker\Packages\Connectors\DataSources\Models\DataSource";
175+
if (!class_exists($class)) {
176+
return;
177+
}
178+
179+
// Check if the data source exists
180+
$dataSource = $class::find($id);
181+
if (!$dataSource) {
182+
return;
183+
}
184+
185+
// Check if the endpoint config exists in the data source
186+
$endpointConfig = Arr::get($dataSource->endpoints, Arr::get($config, 'endpoint', null));
187+
if (!$endpointConfig) {
188+
return;
189+
}
190+
191+
$this->defaultErrorHandling = [
192+
'timeout' => Arr::get($endpointConfig, 'timeout', 0),
193+
'retry_attempts' => Arr::get($endpointConfig, 'retry_attempts', 0),
194+
'retry_wait_time' => Arr::get($endpointConfig, 'retry_wait_time', 5),
195+
];
138196
}
139197
}

‎ProcessMaker/Jobs/RunScriptTask.php‎

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,8 @@ public function action(ProcessRequestToken $token = null, ScriptTaskInterface $e
8181
$script = Script::findOrFail($scriptRef)->versionFor($instance);
8282
}
8383

84-
$errorHandling = new ErrorHandling($token);
85-
86-
/**
87-
* This obtains the initial values and the values configured in the diagram;
88-
* if the diagram values exist, it overwrites the initial values.
89-
*/
90-
$initial = [
91-
'timeout' => $script->timeout,
92-
'retry_attempts' => $script->retry_attempts,
93-
'retry_wait_time' => $script->retry_wait_time,
94-
];
95-
$result = json_decode($element->getProperty('errorHandling'), true) ?? [];
96-
if (is_array($result) && !empty($result)) {
97-
$initial = array_merge($initial, $result);
98-
}
99-
$errorHandling->errorHandling($initial);
84+
$errorHandling = new ErrorHandling($element, $token);
85+
$errorHandling->setDefaultsFromScript($script);
10086

10187
$this->unlock();
10288
$dataManager = new DataManager();

‎ProcessMaker/Jobs/RunServiceTask.php‎

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -86,37 +86,20 @@ public function action(ProcessRequestToken $token = null, ServiceTaskInterface $
8686
throw new ScriptException('Service task not implemented: ' . $implementation);
8787
}
8888

89-
$errorHandling = new ErrorHandling($token);
90-
91-
/**
92-
* This obtains the initial values and the values configured in the diagram;
93-
* if the diagram values exist, it overwrites the initial values.
94-
*/
95-
ErrorHandling::$callback = function ($params) use ($element, $errorHandling) {
96-
$initial = [
97-
'timeout' => $params['timeout'],
98-
'retry_attempts' => $params['retry_attempts'],
99-
'retry_wait_time' => $params['retry_wait_time'],
100-
];
101-
102-
$result = json_decode($element->getProperty('errorHandling'), true) ?? [];
103-
if (is_array($result) && !empty($result)) {
104-
$initial = array_merge($initial, $result);
105-
}
106-
$errorHandling->errorHandling($initial);
107-
};
89+
$errorHandling = new ErrorHandling($element, $token);
90+
$errorHandling->setDefaultsFromDataSourceConfig($configuration);
10891

10992
$this->unlock();
11093
$dataManager = new DataManager();
11194
$data = $dataManager->getData($token);
11295

11396
/**
114-
* todo: Please review the "else" section as it appears unreachable since if `$existsImpl`
97+
* todo: Please review the "else" section as it appears unreachable since if `$existsImpl`
11598
* is not true, an exception is thrown a few lines above.
11699
*/
117100
if ($existsImpl) {
118101
$response = [
119-
'output' => WorkflowManager::runServiceImplementation($implementation, $data, $configuration, $token->getId()),
102+
'output' => WorkflowManager::runServiceImplementation($implementation, $data, $configuration, $token->getId(), $errorHandling->timeout()),
120103
];
121104
} else {
122105
$response = $script->runScript($data, $configuration, $token->getId(), $errorHandling->timeout());
@@ -167,12 +150,6 @@ public function failed(Throwable $exception)
167150

168151
return;
169152
}
170-
if (get_class($exception) === "Illuminate\\Queue\\MaxAttemptsExceededException") {
171-
$message = 'This is a type MaxAttemptsExceededException exception, it appears '
172-
. 'that the global value configured in config/horizon.php has been exceeded '
173-
. 'in the retries. Please consult with your main administrator.';
174-
Log::error($message);
175-
}
176153
Log::error('Script (#' . $this->tokenId . ') failed: ' . $exception->getMessage());
177154
Log::error($exception->getTraceAsString());
178155
$token = ProcessRequestToken::find($this->tokenId);

‎ProcessMaker/Nayra/Managers/WorkflowManagerDefault.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,11 @@ class_exists($this->serviceTaskImplementations[$implementation]);
357357
*
358358
* @return mixed
359359
*/
360-
public function runServiceImplementation($implementation, array $data, array $config, $tokenId = '')
360+
public function runServiceImplementation($implementation, array $data, array $config, $tokenId = '', $timeout = 0)
361361
{
362362
$class = $this->serviceTaskImplementations[$implementation];
363363
$service = new $class();
364364

365-
return $service->run($data, $config, $tokenId);
365+
return $service->run($data, $config, $tokenId, $timeout);
366366
}
367367
}

‎ProcessMaker/Traits/MakeHttpRequests.php‎

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ trait MakeHttpRequests
3535

3636
private $mustache = null;
3737

38+
private $timeout = 0;
39+
3840
private function getMustache()
3941
{
4042
if ($this->mustache === null) {
@@ -202,12 +204,6 @@ private function prepareRequestWithOutboundConfig(array $requestData, array &$co
202204

203205
$request = [$method, $url, $headers, $body, $bodyType];
204206
$request = $this->addAuthorizationHeaders(...$request);
205-
//todo: The values of $endpoint must be passed somehow to RunServiceTask inside action method.
206-
207-
if (is_callable(ErrorHandling::$callback)) {
208-
$fn = ErrorHandling::$callback;
209-
$fn($endpoint);
210-
}
211207

212208
return $request;
213209
}
@@ -436,8 +432,9 @@ private function call($method, $url, array $headers, $body, $bodyType)
436432
{
437433
$client = $this->client ?? app()->make(Client::class, [
438434
'config' => [
439-
'verify' => $this->verifySsl
440-
]
435+
'verify' => $this->verifySsl,
436+
'timeout' => $this->timeout,
437+
],
441438
]);
442439
$options = [];
443440
if ($bodyType === 'form-data') {

0 commit comments

Comments
 (0)