Skip to content

Commit 33a132f

Browse files
committed
11.1.8: * [Performance/Worklists/Export] Optimized bulk-loading of custom fields in worklist exports for better performance.
1 parent 75503ef commit 33a132f

File tree

3 files changed

+69
-19
lines changed

3 files changed

+69
-19
lines changed

features/cerberusweb.core/api/uri/internal/worklists.php

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -913,10 +913,6 @@ private function _viewIncrementExportAsCsv(array &$cursor) {
913913
if(null == ($context_ext = Extension_DevblocksContext::getByViewClass(get_class($view), true)))
914914
return;
915915

916-
$global_labels = $global_values = [];
917-
CerberusContexts::getContext($context_ext->id, null, $global_labels, $global_values, null, true);
918-
$global_types = $global_values['_types'];
919-
920916
// Append mode to the temp file
921917
if(!($fp = fopen($cursor['temp_file'], "a")))
922918
return;
@@ -927,6 +923,9 @@ private function _viewIncrementExportAsCsv(array &$cursor) {
927923
$dicts = [];
928924

929925
if('kata' == $cursor['export_mode']) {
926+
// Bulk lazy load custom fields across the dictionaries
927+
DevblocksDictionaryDelegate::bulkLazyLoad($dicts, 'customfields');
928+
930929
$export_columns = $this->_getExportColumnsKataFromCursor($cursor);
931930

932931
// If the first page, add headings
@@ -953,6 +952,10 @@ private function _viewIncrementExportAsCsv(array &$cursor) {
953952
}
954953

955954
} else {
955+
$global_labels = $global_values = [];
956+
CerberusContexts::getContext($context_ext->id, null, $global_labels, $global_values, null, true);
957+
$global_types = $global_values['_types'];
958+
956959
// Bulk lazy load the tokens across all the dictionaries with a temporary cache
957960
foreach($cursor['tokens'] as $token) {
958961
DevblocksDictionaryDelegate::bulkLazyLoad($dicts, $token);
@@ -1021,10 +1024,6 @@ private function _viewIncrementExportAsJson(array &$cursor) {
10211024
if(null == ($context_ext = Extension_DevblocksContext::getByViewClass(get_class($view), true)))
10221025
return;
10231026

1024-
$global_labels = $global_values = [];
1025-
CerberusContexts::getContext($context_ext->id, null, $global_labels, $global_values, null, true);
1026-
$global_types = $global_values['_types'];
1027-
10281027
// Append mode to the temp file
10291028
if(!($fp = fopen($cursor['temp_file'], "a")))
10301029
return;
@@ -1035,6 +1034,9 @@ private function _viewIncrementExportAsJson(array &$cursor) {
10351034
$dicts = [];
10361035

10371036
if('kata' == $cursor['export_mode']) {
1037+
// Bulk lazy load custom fields across the dictionaries
1038+
DevblocksDictionaryDelegate::bulkLazyLoad($dicts, 'customfields');
1039+
10381040
$export_columns = $this->_getExportColumnsKataFromCursor($cursor);
10391041

10401042
fputs($fp, "{\"results\": [\n");
@@ -1056,6 +1058,10 @@ private function _viewIncrementExportAsJson(array &$cursor) {
10561058
fputs($fp, $json);
10571059

10581060
} else {
1061+
$global_labels = $global_values = [];
1062+
CerberusContexts::getContext($context_ext->id, null, $global_labels, $global_values, null, true);
1063+
$global_types = $global_values['_types'];
1064+
10591065
// Bulk lazy load the tokens across all the dictionaries with a temporary cache
10601066
foreach($cursor['tokens'] as $token) {
10611067
DevblocksDictionaryDelegate::bulkLazyLoad($dicts, $token);
@@ -1134,10 +1140,6 @@ private function _viewIncrementExportAsJsonl(array &$cursor) {
11341140
if(null == ($context_ext = Extension_DevblocksContext::getByViewClass(get_class($view), true)))
11351141
return;
11361142

1137-
$global_labels = $global_values = [];
1138-
CerberusContexts::getContext($context_ext->id, null, $global_labels, $global_values, null, true);
1139-
$global_types = $global_values['_types'];
1140-
11411143
// Append mode to the temp file
11421144
if(!($fp = fopen($cursor['temp_file'], "a")))
11431145
return;
@@ -1148,6 +1150,9 @@ private function _viewIncrementExportAsJsonl(array &$cursor) {
11481150
$dicts = [];
11491151

11501152
if('kata' == $cursor['export_mode']) {
1153+
// Bulk lazy load custom fields across the dictionaries
1154+
DevblocksDictionaryDelegate::bulkLazyLoad($dicts, 'customfields');
1155+
11511156
$export_columns = $this->_getExportColumnsKataFromCursor($cursor);
11521157

11531158
foreach($dicts as $dict) {
@@ -1163,6 +1168,10 @@ private function _viewIncrementExportAsJsonl(array &$cursor) {
11631168
}
11641169

11651170
} else {
1171+
$global_labels = $global_values = [];
1172+
CerberusContexts::getContext($context_ext->id, null, $global_labels, $global_values, null, true);
1173+
$global_types = $global_values['_types'];
1174+
11661175
// Bulk lazy load the tokens across all the dictionaries with a temporary cache
11671176
foreach($cursor['tokens'] as $token) {
11681177
DevblocksDictionaryDelegate::bulkLazyLoad($dicts, $token);
@@ -1220,6 +1229,9 @@ private function _viewIncrementExportAsXml(array &$cursor) {
12201229
$dicts = [];
12211230

12221231
if('kata' == $cursor['export_mode']) {
1232+
// Bulk lazy load custom fields across the dictionaries
1233+
DevblocksDictionaryDelegate::bulkLazyLoad($dicts, 'customfields');
1234+
12231235
$export_columns = $this->_getExportColumnsKataFromCursor($cursor);
12241236

12251237
if(0 == $cursor['page']) {

libs/devblocks/api/Extension.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,7 +1686,7 @@ protected function _importModelCustomFieldsAsValues($model, $token_values) {
16861686
}
16871687

16881688
protected function _lazyLoadDefaults($token, array $dictionary=[]) {
1689-
if(!$token)
1689+
if(!$token || $token == '__expandable')
16901690
return [];
16911691

16921692
$context = $dictionary['_context'] ?? null;
@@ -1695,7 +1695,7 @@ protected function _lazyLoadDefaults($token, array $dictionary=[]) {
16951695
if(!$context || !$context_id)
16961696
return [];
16971697

1698-
if(false == ($context_ext = Extension_DevblocksContext::getByAlias($context, true)))
1698+
if(!($context_ext = Extension_DevblocksContext::getByAlias($context, true)))
16991699
return [];
17001700

17011701
$context = $context_ext->id;
@@ -1917,6 +1917,10 @@ protected function _lazyLoadLinks($token, $context, $context_id) {
19171917

19181918
return $token_values;
19191919
}
1920+
1921+
public function lazyLoadCustomFields($token, $context, $context_id, $as_keys=true, $field_values=null, array $dictionary=[]) : array {
1922+
return $this->_lazyLoadCustomFields($token, $context, $context_id, $as_keys, $field_values, $dictionary);
1923+
}
19201924

19211925
// [TODO] This is setting the wrong type on all linked fields
19221926
/**

libs/devblocks/api/services/template_builder.php

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,10 +1077,9 @@ public static function bulkLazyLoad(array $dicts, $token, $skip_meta=false) {
10771077
if(empty($dicts))
10781078
return;
10791079

1080-
// [TODO] Don't run (n) queries to lazy load custom fields
1080+
/** @var $dicts DevblocksDictionaryDelegate[] */
10811081

10821082
// Examine contexts on the first dictionary
1083-
/* @var DevblocksDictionaryDelegate $first_dict */
10841083
$first_dict = reset($dicts);
10851084

10861085
if(!($first_dict instanceof DevblocksDictionaryDelegate))
@@ -1130,17 +1129,52 @@ public static function bulkLazyLoad(array $dicts, $token, $skip_meta=false) {
11301129

11311130
// Load the contexts from the cache
11321131
foreach($dicts as $dict) {
1133-
$dict->$prefix_key;
1132+
$dict->get($prefix_key);
11341133
}
11351134

11361135
// Flush the temporary cache
11371136
CerberusContexts::setCacheLoads($was_caching_loads);
11381137
}
11391138
}
11401139

1141-
// Now load the tokens, since we probably already lazy loaded the contexts
1140+
// Bulk load outer dictionary custom fields
1141+
if($token == 'customfields'
1142+
&& ($context_ext_id = $contexts['']['context'] ?? '')
1143+
&& ($context_ext = Extension_DevblocksContext::get($context_ext_id))
1144+
) {
1145+
// Load a full page of custom field values at once
1146+
$field_values = DAO_CustomFieldValue::getValuesByContextIds($context_ext->id, array_column($dicts, 'id'));
1147+
1148+
if(is_array($field_values)) {
1149+
foreach($dicts as $dict) {
1150+
if(!($dict_id = $dict->get('id')))
1151+
continue;
1152+
1153+
if(array_key_exists($dict_id, $field_values)) {
1154+
$custom_values = $context_ext->lazyLoadCustomFields(
1155+
$token,
1156+
$context_ext->id,
1157+
$dict_id,
1158+
true,
1159+
$field_values[$dict_id],
1160+
$dict->getDictionary()
1161+
);
1162+
1163+
$dict->mergeKeys(null, $custom_values);
1164+
$dict->set($token, array_keys($custom_values));
1165+
1166+
} else {
1167+
$dict->set($token, []);
1168+
}
1169+
1170+
}
1171+
}
1172+
return;
1173+
}
1174+
1175+
// Now load the tokens, since we probably already lazy-loaded the contexts
11421176
foreach($dicts as $dict) { /* @var $dict DevblocksDictionaryDelegate */
1143-
$dict->$token;
1177+
$dict->get($token);
11441178
}
11451179
}
11461180
};

0 commit comments

Comments
 (0)