Problem/Motivation

My team uses preinstalled Drupal instance (with memcache) for testing. To test a time-based caching workaround, I need to be able to mock (request) time.

Proposed resolution

In MemcacheBackend::getRequestTime(), use the core time service to get the request time as the first attempt, and fall back to the actual code if it fails.

Remaining tasks

TBD.

User interface changes

Nothing.

API changes

Nothing (?)

Data model changes

Nothing.

Issue fork memcache-2999614

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

visabhishek created an issue. See original summary.

visabhishek’s picture

Status: Active » Needs review
StatusFileSize
new2.44 KB

Uploading initial patch

fabianx’s picture

Priority: Normal » Major
Issue tags: +stable release blocker

The idea is good, but we cannot rely on ::time() as we are so low level that we need to work within the bootstrap container as well and request() needs the request, which does not exist at that time.

Brandon already tried that.

We could rely on the timestampInvalidation() service however, which we already inject.

Main thing changes is that we effectively use time() instead of REQUEST_TIME for new entries then.

bdragon’s picture

However, the ones in MemcacheStatisticsController look fine to me. I will review all handling of time today and update things to the new apis where it makes sense.

  • visabhishek authored 58b9eb9 on 8.x-2.x
    Issue #2999614 by visabhishek: Replace uses of deprecated functions
    

  • 3a623de committed on 8.x-2.x
    Revert "Issue #2999614 by visabhishek: Replace uses of deprecated...
bdragon’s picture

I rolled the ones in MemcacheStatisticsController into a memcache_admin commit I just did. The other bits still need further review. (committed and reverted them after I realized I had pushed the wrong part.)

fabianx’s picture

Issue tags: -stable release blocker

We can just use our own definition of REQUEST_TIME instead once 9.x comes around.

Unless we want to change the behavior, there is no need now.

japerry’s picture

StatusFileSize
new2.84 KB

Whelp D9 is (soon) out. Re-implemented REQUEST_TIME as our own definition. People were seeing issues with the time service in the deprecated report, which I think is related to this issue. This shouldn't change the timestamps unless the global is missing. But honestly, that is what core is doing, so I don't think its much of a change.

dqd’s picture

+++ b/src/Invalidator/TimestampInvalidatorInterface.php
@@ -58,4 +58,17 @@ interface TimestampInvalidatorInterface {
+  /**
+   * Get the current request time
+   *
+   * Memcache operates within the bootstrap container, so only the REQUEST_TIME
+   * global is (possibly) available. The request object and time service aren't.
+   * Return the global or time() if need be.
+   *
+   * @see https://www.drupal.org/node/2999614 for more info.
+   *
+   * @return int
+   *   A Unix timestamp.
+   */
+  public function getRequestTime();
 }

+1 for working on this! Short review: Not sure if it covers all spots yet but it looks good and simple to me from a short glimpse. But I would maybe discuss the code comments with someone (else than me). Especially 62-75 in TimestampInvalidatorInterface.php?

berdir’s picture

REQUEST_TIME IS *not* removed in Drupal 9, that has been pushed to D10, so this is not a blocker.

berdir’s picture

Also, I think the bug around this might actually have been fixed and it might just work now, haven't tried yet with redis.

japerry’s picture

Title: Replace uses of deprecated functions » Update REQUEST_TIME call
Status: Needs review » Postponed

Setting postponed for after the D9 release since its no longer a blocker. Hopefully then we can refactor correctly per Berdir's comment with the time service.

dqd’s picture

REQUEST_TIME IS *not* removed in Drupal 9, that has been pushed to D10

@#11: ah! didn't know that, Thanks!

Also, I think the bug around this might actually have been fixed.

Do you have a link to an issue or some quick words helping to find the spots?

@japerry: I think we can forget #10 then ... which was made in a rush.

berdir’s picture

dqd’s picture

@berdir: Thanks a million!

huzooka’s picture

Assigned: Unassigned » huzooka
Status: Postponed » Active

My team uses preinstalled Drupal instance for testing and in case of a time-based caching workaround, I need to be able to mock (request) time.

Re #3

The idea is good, but we cannot rely on ::time() as we are so low level that we need to work within the bootstrap container as well and request() needs the request, which does not exist at that time.

What if we follow the same logic as we have at ::debug()? So, trying to return \Drupal::time()->getRequestTime() and if it fails, fall back to the actual logic (int) $_SERVER['REQUEST_TIME'] ?? time();

Also,

  1. It is unclear to me why this issue is postponed - maybe it was just stuck in this state accidentally?
  2. My suggestion is to change this to a task (or to a feature request). Imho this is not a bug anymore.

I want to share my local path with you.

huzooka’s picture

Assigned: huzooka » Unassigned
Priority: Major » Normal
Issue summary: View changes
Status: Active » Needs review

* Updated (created) issue summary.
* Changed category to feature request.
* Changed priority to normal.

Feel free to change them if you disagree.

huzooka’s picture

I see a test failure with the next minor core release, but imho it is a preexisting issue.

andypost’s picture

Status: Needs review » Needs work

it affects performance as instead of variable (expected and documented) we'll get a set of function calls for no reason (each get doing validation and each invalidate of tag)

generally not clear why this method is public at all and moreover not clear why it has no static cache for result now

huzooka’s picture

Assigned: Unassigned » huzooka
huzooka’s picture

Assigned: huzooka » Unassigned
Status: Needs work » Needs review

Forgot to unassign

japerry’s picture

I made two changes to the MR:

1. The static cache added in the second commit doesn't work. Once getRequestTime has captured a value it never consults the service again, so swapping datetime.time afterwards is useless. The new kernel test `MemcacheBackendTest::testRequestTimeUsesTimeService()` fails with the static cache and on 8.x-2.x, and passes with this rework.

2. On @andypost's performance point: the cost that matters is not the function call but the try/catch. `\Drupal::time()` throws when the container is not set yet, and this backend serves cache.container, so those early reads each paid for a thrown exception. The rework checks `\Drupal::hasContainer()` / `\Drupal::hasService('datetime.time')` first instead, which is a cheap method call per `valid()` on a normal request and no exception during bootstrap.

  • japerry committed e658e2ef on 8.x-2.x
    Issue #2999614 by huzooka, visabhishek, japerry: drop the static request...

  • japerry committed fda43957 on 8.x-2.x authored by huzooka
    Issue #2999614: Add static cache for request timestamp.
    

  • japerry committed f5be9bb3 on 8.x-2.x authored by huzooka
    Issue #2999614: Use Drupal core time service with fallback
    
japerry’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.