How can I share cache with multiple users and roles? In my custom module, I define a custom block that performs an expensive operation:

/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data();
  $agent_number = get_agent_number_from_context();
  return [
    '#theme' =&gt; 'my_custom_module',
    '#cache' =&gt; [
      'keys' =&gt; ['my_block', 'full_version', $agent_number],
      'tags' =&gt; ['my_custom_module'],
      'max-age' =&gt; 86400,
    ],
  ];
}


The caching works except when another user views the block or a user with a different role view the page; it creates a new cache item. Is it possible to have cache only one time for multiple users/roles?

Edit

I tried the following (ended up using route context just to not add another variable to my problem):

/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data();
  return [
    '#theme' =&gt; 'my_custom_module',
    '#data' =&gt; $data,
    '#cache' =&gt; [
      'contexts' =&gt; ['route'],
      'tags' =&gt; ['my_module'],
      'max-age' =&gt; 86400,
    ],
  ];
}


Noticed when I had the block using Layout Builder via Page Manager, no item got added to the cache_render table (that might be a separate issue).  When I added the block on default Drupal Block Layout I noticed that it still created a new cache record for every user.  For example:

User 1 navigated to: /my-account/A123 and the following record got added to the cache_render table:

cid

entity_view:block:mycustomblock:[languages:language_interface]=en:[route]=entity.node.canonical7ccb4f15749b8c9e759f0016bfc863bd5e6bef88ea0a9dfe7b1cbe2687d30b32:[theme]=my_theme:[url.site]=http://mysite.test:[user]=1


tags

block_view config:block.block.mycustomblock config:user.role.administrator config:user.role.authenticated my_module rendered user:1


User 72 navigated to: /my-account/A123 and the following record got added to the cache_render table:

cid

entity_view:block:mycustomblock:[languages:language_interface]=en:[route]=entity.node.canonical7ccb4f15749b8c9e759f0016bfc863bd5e6bef88ea0a9dfe7b1cbe2687d30b32:[theme]=my_theme:[url.site]=http://mysite.test:[user]=79


tags

block_view config:block.block.mycustomblock config:user.role.agent config:user.role.authenticated my_module rendered user:79


With using contexts, I am still seeing it create a new record for every user.

Edit 3

I think my test form Edit 2 is invalid because I was trying to make the block work outside of page manager but I needed the context from page manager so it was using the logged-in users. Long story short, I need to figure out why context caching isn't working (although key caching is working) when using Page Manager or Layout Manager.
Caching is shared with multiple users or roles by default, unless you add a cache context like user or user.roles.

Otherwise it's hard to tell what the code in the question wants to achieve.


If it wants to set block cache keys, then you can't do it from here
and you don't need to. They're set automatically.
get_agent_number_from_context() should probably be a custom
cache_context.agent_number which you then could add to the block
build array to vary the cached block by this variable: 

/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data();
  return [
    '#theme' =&gt; 'my_custom_module',
    '#data' =&gt; $data,
    '#cache' =&gt; [
      'contexts' =&gt; ['agent_number'],
      'max-age' =&gt; 86400,
    ],
  ];
}


How to create a custom cache context:
https://www.drupal.org/docs/8/api/cache-api/cache-contexts#recognize-discover-create
If it wants to cache the expensive data on its own (which
makes sense if you want to reuse the rendered result in other places
not necessarily blocks), then you need to execute
get_expensive_data() in a #pre_render callback to avoid that it
gets executed in case of a cache hit. See
https://dev.acquia.com/blog/drupal-8-performance-render-caching


Edit 1:
The cids you have added to the question contain a cache context for the user. I can't tell by the code shown so far how it ends up in your block. But there is also a cache tag of the user, so there has to be some code retrieving and rendering the current user.

Edit 2:
Assuming the theme is the same there is also a default user.permissions cache context for all render caching which probably kicks in now that user is removed. See https://www.drupal.org/project/drupal/issues/2493033