Skip to content

Commit

Permalink
Merge pull request #7858 from ProcessMaker/FOUR-21383
Browse files Browse the repository at this point in the history
FOUR-21383 Improve screen cache usage
  • Loading branch information
caleeli authored Jan 4, 2025
2 parents 58433ea + 9008be1 commit d061116
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 6 deletions.
9 changes: 7 additions & 2 deletions ProcessMaker/Http/Controllers/TaskController.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ public function edit(ProcessRequestToken $task, string $preview = '')
MarkNotificationAsRead::dispatch([['url', '=', '/' . Request::path()]], ['read_at' => Carbon::now()]);

$manager = app(ScreenBuilderManager::class);
event(new ScreenBuilderStarting($manager, $task->getScreenVersion() ? $task->getScreenVersion()->type : 'FORM'));
$screenVersion = $task->getScreenVersion();
event(new ScreenBuilderStarting($manager, $screenVersion ? $screenVersion->type : 'FORM'));

$submitUrl = route('api.tasks.update', $task->id);
$task->processRequest;
$task->user;
$screenVersion = $task->getScreenVersion();
$task->component = $screenVersion ? $screenVersion->parent->renderComponent() : null;
$task->screen = $screenVersion ? $screenVersion->toArray() : null;
$task->request_data = $dataManager->getData($task);
Expand All @@ -98,6 +98,11 @@ public function edit(ProcessRequestToken $task, string $preview = '')
$screenFields = $screenVersion ? $screenVersion->screenFilteredFields() : [];
$taskDraftsEnabled = TaskDraft::draftsEnabled();

// Remove screen parent to reduce the size of the response
$screen = $task->screen;
$screen['parent'] = null;
$task->screen = $screen;

if ($element instanceof ScriptTaskInterface) {
return redirect(route('requests.show', ['request' => $task->processRequest->getKey()]));
} else {
Expand Down
40 changes: 36 additions & 4 deletions ProcessMaker/Traits/HasScreenFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Support\Arr;
use Log;
use ProcessMaker\Cache\Screens\ScreenCacheFactory;
use ProcessMaker\Models\Column;
use ProcessMaker\Models\Screen;

Expand All @@ -19,10 +20,7 @@ public function getFieldsAttribute()
{
if (empty($this->parsedFields)) {
try {
$this->parsedFields = collect([]);
if ($this->config) {
$this->walkArray($this->config);
}
$this->loadScreenFields();
} catch (\Throwable $e) {
Log::error("Error encountered while retrieving fields for screen #{$this->id}", [
'message' => $e->getMessage(),
Expand All @@ -39,6 +37,40 @@ public function getFieldsAttribute()
return $this->parsedFields->unique('field');
}

/**
* Load the fields for the screen and cache them
*
* @return void
*/
private function loadScreenFields()
{
$screenCache = ScreenCacheFactory::getScreenCache();
// Create cache key
$screenId = $this instanceof Screen ? $this->id : $this->screen_id;
$screenVersionId = $this instanceof Screen ? 0 : $this->id;
$key = $screenCache->createKey([
'process_id' => 0,
'process_version_id' => 0,
'language' => 'all',
'screen_id' => (int) $screenId,
'screen_version_id' => (int) $screenVersionId,
]) . '_fields';

// Try to get the screen fields from cache
$parsedFields = $screenCache->get($key);

if (!$parsedFields || collect($parsedFields)->isEmpty()) {
$this->parsedFields = collect([]);
if ($this->config) {
$this->walkArray($this->config);
}

$screenCache->set($key, $this->parsedFields);
} else {
$this->parsedFields = collect($parsedFields);
}
}

public function parseNestedScreen($node)
{
$nested = Screen::find($node['config']['screen']);
Expand Down
142 changes: 142 additions & 0 deletions tests/unit/ProcessMaker/HasScreenFieldsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php

use Tests\TestCase;
use ProcessMaker\Cache\Screens\ScreenCacheFactory;
use ProcessMaker\Models\Screen;

class HasScreenFieldsTest extends TestCase
{
public function testLoadScreenFields()
{
$screenCache = ScreenCacheFactory::getScreenCache();
$screen = Screen::factory()->create([
'id' => 1,
'config' => [
[
'items' => [
[
'component' => 'FormInput',
'config' => [
'name' => 'field1',
'label' => 'Field 1',
'dataFormat' => 'string',
],
],
[
'component' => 'FormInput',
'config' => [
'name' => 'field2',
'label' => 'Field 2',
'dataFormat' => 'string',
],
],
],
],
],
]);
$expectedFields = [
[
'label' => 'Field 1',
'field' => 'field1',
'sortable' => true,
'default' => false,
'format' => 'string',
'mask' => null,
'isSubmitButton' => false,
'encryptedConfig' => null,
],
[
'label' => 'Field 2',
'field' => 'field2',
'sortable' => true,
'default' => false,
'format' => 'string',
'mask' => null,
'isSubmitButton' => false,
'encryptedConfig' => null,
],
];
$key = $screenCache->createKey([
'process_id' => 0,
'process_version_id' => 0,
'language' => 'all',
'screen_id' => (int) $screen->id,
'screen_version_id' => 0,
]) . '_fields';
$screenCache->set($key, null);

$fields = json_decode(json_encode($screen->fields), true);

$cacheFields = json_decode(json_encode($screenCache->get($key)), true);

$this->assertEquals($expectedFields, $fields);
$this->assertEquals($expectedFields, $cacheFields);
}

public function testLoadScreenFieldsFromCache()
{
$screenCache = ScreenCacheFactory::getScreenCache();
$screen = Screen::factory()->create([
'id' => 1,
'config' => [
[
'items' => [
[
'component' => 'FormInput',
'config' => [
'name' => 'field1',
'label' => 'Field 1',
'dataFormat' => 'string',
],
],
[
'component' => 'FormInput',
'config' => [
'name' => 'field2',
'label' => 'Field 2',
'dataFormat' => 'string',
],
],
],
],
],
]);
$expectedFields = [
[
'label' => 'Field 1 (cached)',
'field' => 'field1',
'sortable' => true,
'default' => false,
'format' => 'string',
'mask' => null,
'isSubmitButton' => false,
'encryptedConfig' => null,
],
[
'label' => 'Field 2 (cached)',
'field' => 'field2',
'sortable' => true,
'default' => false,
'format' => 'string',
'mask' => null,
'isSubmitButton' => false,
'encryptedConfig' => null,
],
];
$key = $screenCache->createKey([
'process_id' => 0,
'process_version_id' => 0,
'language' => 'all',
'screen_id' => (int) $screen->id,
'screen_version_id' => 0,
]) . '_fields';
$screenCache->set($key, $expectedFields);

$fields = json_decode(json_encode($screen->fields), true);

$cacheFields = json_decode(json_encode($screenCache->get($key)), true);

$this->assertEquals($expectedFields, $fields);
$this->assertEquals($expectedFields, $cacheFields);
}
}

0 comments on commit d061116

Please sign in to comment.