Fusion Cache Identifier calculation

Hey guys, I am currently debugging an “issue” with the fusion cache.

Given I have a fusion prototype with a cache configuration like:

@cache {
    mode = 'cached'
    entryIdentifier {
        staticIdentifier = 'aStaticPartHardToCalculate'
    }
}

I want to have that fusion prototype be cached and reused whereever it is used.

I had the strange behavior that the element is re-generated over and over again. The reason is that the fusion path is used as part of the cache identifier in https://github.com/neos/neos-development-collection/blob/e24147fc4266a217e8c503bfa6dade078418b191/Neos.Fusion/Classes/Core/Cache/ContentCache.php#L185

return md5($fusionPath . '@' . $identifierSource);

That means, even if the prototype is cached with an static identifier, it is cached dependend on the fusion path which means it is at least cached separately for every document type.

Is there a reason to not cache the prototype independently?

there is, because we cannot know if you use any context variables in there, which might be different depending on path.

makes sense :frowning:

But I would be VERY much in favor of making this possible if wanted/needed

Couldn’t we skip the path if the context section is defined?

I think you should be able to circumvent this by using Neos.Fusion:Renderer like this:

# use this anywhere you like
result = Neos.Fusion:Renderer {
  	renderPath = "/cachedFragment"
}

# global path with @cache
cachedFragment = Neos.Fusion:Value {
	
	value = ...
	
	@cache {
	    mode = 'cached'
	    entryIdentifier {
	        staticIdentifier = 'aStaticPartHardToCalculate'
	    }
	}
}

A global path for global fragment seems legit to me.

2 Likes

Good idea, but renderer internally applies it’s own path to the used render prototype, so it will still render with different paths

Coorected the example you have to add a “/” at the begining of the renderPath

1 Like

We just used the same technique and built a small wrapper, to easily cache several components globally

prototype(Some.Project:GlobalCacheWrapper) < prototype(Neos.Fusion:Component) {
  content = ''
  entryIdentifier = ${[]}
  entryTags = ${[]}

  renderer = Neos.Fusion:Renderer {
      renderPath = '/globalCacheSegment'

      @context {
          content = ${props.content}
          entryIdentifier = ${props.entryIdentifier}
          entryTags = ${props.entryTags}
      }
   }
}

globalCacheSegment = Neos.Fusion:Value {
  value = ${content}

  @cache {
      mode = 'cached'

      entryIdentifier {
          @apply.identifier = ${entryIdentifier}
      }

      entryTags {
          # Needs to be a 1D array
          entryTags = ${entryTags}
      }
   }
}
4 Likes