Cache the TemplateResource reference ID like an attribute

TemplateResources can have their reference ID defined by an OS::stack_id
output in the template. However getting it - or just checking that it even
exists - is very expensive, and it happens virtually every time we load the
stack in memory for any reason.

Since when the output is present the reference ID is also available as an
attribute, simply cache it in the database as if it were an attribute
regardless of whether the output exists. Once it is in the cache,
subsequent accesses will be cheap just like they are for attributes.

Keep previous performance optimisations in place as well, since attributes
are not stored in the database in the legacy path (so legacy stacks don't
benefit from this change), and since the cache does get invalidated e.g. on
every stack update.

Change-Id: Ib9cd0aa40d377ec227754e386e02f185fd871909
Closes-Bug: #1742847
Related-Bug: #1719333
This commit is contained in:
Zane Bitter 2018-01-11 20:11:04 -05:00
parent f965ff615e
commit 3cd84afcfc
1 changed files with 7 additions and 9 deletions

View File

@ -60,8 +60,6 @@ class TemplateResource(stack_resource.StackResource):
self.stack = stack
self.validation_exception = None
self._reference_id = None
tri = self._get_resource_info(json_snippet)
self.properties_schema = {}
@ -308,14 +306,15 @@ class TemplateResource(stack_resource.StackResource):
if self.resource_id is None:
return six.text_type(self.name)
if self._reference_id is not None:
return self._reference_id
if STACK_ID_OUTPUT in self.attributes.cached_attrs:
return self.attributes.cached_attrs[STACK_ID_OUTPUT]
stack_identity = self.nested_identifier()
reference_id = stack_identity.arn()
try:
if self._outputs is not None:
self._reference_id = self.get_output(STACK_ID_OUTPUT)
reference_id = self.get_output(STACK_ID_OUTPUT)
elif STACK_ID_OUTPUT in self.attributes:
output = self.rpc_client().show_output(self.context,
dict(stack_identity),
@ -325,15 +324,14 @@ class TemplateResource(stack_resource.StackResource):
resource=self.name,
attribute=STACK_ID_OUTPUT,
message=output[rpc_api.OUTPUT_ERROR])
self._reference_id = output[rpc_api.OUTPUT_VALUE]
reference_id = output[rpc_api.OUTPUT_VALUE]
except exception.TemplateOutputError as err:
LOG.info('%s', err)
except exception.NotFound:
pass
else:
return self._reference_id
return stack_identity.arn()
self.attributes.set_cached_attr(STACK_ID_OUTPUT, reference_id)
return reference_id
def get_attribute(self, key, *path):
if self.resource_id is None: