Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] OAI controller runs out of memory on deletion of expired tokens #1096

Open
michaelkubina opened this issue Nov 21, 2023 · 1 comment
Open
Labels
🐛 bug A non-security related bug. 🛠 maintenance A task to keep the code up-to-date and manageable.

Comments

@michaelkubina
Copy link
Collaborator

Description

During OAI harvesting, resumptionTokens are created in the TokenRepository if the number of returned items exceeds the settings.limit (e.g 50 records). The main action of the OAI controller deletes expired tokens, that reach their lifetime determined by settings.expired (e.g. 1800 seconds), once a new main action is executed. We ran into situations, where the OAI interface "freezed" and returned a blank page without a warning.

A deeper look into the issue showed, that it had indirectly to do with the settings.expired and that we were only able to get our OAI running again, by deleting the tokens in tx_dlf_tokens and setting the expire time unreasonably low (e.g. 60 seconds). The reason is, that the deletion of expired tokens caused an internal server error (500), because the script reached the php memory_limit. And the reason for this is, that:

We get into a situation like this, for example if:

  • a client is successfully harvesting all of our records in quick intervals, so that only a handfull of tokens are expired at a given moment and will get deleted properly
  • but leaving hundreds of tokens still valid until they reach their actual expiration date
  • then maybe a few hours or days later another clients wants to harvest and suddenly in the main action hundreds of tokens are flagged as expired, which results in the said internal server error due to reaching the memory_limit

Reproduction

Steps to reproduce the behaviour:

  1. set up a php memory_limit of e.g. 512MB or 1GB

  2. Go to your OAI plugin and set a limit of e.g. 50 and a lifetime of e.g. 1800 seconds

  3. navigate to your OAI controller and listRecords as mets, dc or epicur over all your records in a reasonable fast interval (1-5 seconds)

  4. harvest multiple times if necessary, so that you amount for several hundred resumption tokens in the database

  5. after being done harvesting wait for e.g. an hour (at least long enough, so that alle tokens are considered expired) and try to listRecords again

  6. you should see a blank page

Expected Behavior

When deleting expired tokens, we should not put all expired tokens in a single big variable $tokensToBeRemoved and iterate over it because it could reach extraordinary sizes. Instead we should query and delete each expired token individualy.

I was thinking about something like this ... but maybe there are better ways or maybe typo3 offers a less memory expensive way to do the current way? Do we need to get the whole token with its options, that take up so much memory or can it be done just by uid?

Pseudo-code to delete expired tokens directly and individually (many consecutive queries):

public function deleteExpiredTokens($expireTime)
{
      $query = $this->createQuery();

      $constraints = [];

      $constraints[] = $query->lessThan('tstamp', (int) (time() - $expireTime));

      if (count($constraints)) {
	      foreach ($contraints as $constraint) {
		      $query->matching($constraint);
		      $tokenToBeRemoved = $query->execute();
		      $this->remove($tokenToBeRemoved);
	      }
      }
}

Additional Context

We actually want to configure our OAI so it reflects the settings used by the DNB...namely 50 records per response and a lifetime of up to 30minutes (https://www.dnb.de/EN/Professionell/Metadatendienste/Datenbezug/OAI/_content/faqOai12_akk.html). While 50 records per response seems reasonable and uncritical, the lifetime of 1800 seconds may cause a huge block of expired tokens, that run into the described memory issue.

@sebastian-meyer
Copy link
Member

I think the right approach here would be to not handle maintenance tasks like purging invalid resumption tokens in an action controller at all. Instead, this should be implemented as a task for the TYPO3 Scheduler. That way it wouldn't encumber the controller any more and it could be executed regularly without depending on someone executing the controller action...

@sebastian-meyer sebastian-meyer added 🐛 bug A non-security related bug. 🛠 maintenance A task to keep the code up-to-date and manageable. labels Jan 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug A non-security related bug. 🛠 maintenance A task to keep the code up-to-date and manageable.
Projects
None yet
Development

No branches or pull requests

2 participants