Skip to content

[Storage]: Improvement idea for StorageWrapper to allow calling register with client-creating-closure or separate registerClosure #9725

Description

@indreka

Main problem/friction we are having right now is that we have some parts of code that use file accesses via gs://bucketname/path/filename
Due to this in the overall init code for entire application we call

StreamWrapper::register(new StorageClient($config), 'gs');

At the same time we have plenty of API call paths that do not interact with the google storage at all but some flow still may trigger it.
Due to this we are instantiating the client and loading lots of classes without actual need (only 100% confirmed at end of API request).

By adding something like:

  private static $clientClosures = [];

  public static function registerLazyClosure(\Closure $clientClosure, $protocol = null)
  {
    $protocol = $protocol ?: self::DEFAULT_PROTOCOL;
    if (!in_array($protocol, stream_get_wrappers())) {
      if (!stream_wrapper_register($protocol, self::class, STREAM_IS_URL)) {
        throw new \RuntimeException("Failed to register '$protocol://' protocol");
      }
      self::$clientClosures[$protocol] = $clientClosure;
      return true;
    }
    return false;
  }

and changing getClient and unregister to:

  public static function getClient($protocol = null)
  {
    $protocol = $protocol ?: self::DEFAULT_PROTOCOL;
    if (isset(self::$clientClosures[$protocol])) {
      self::$clients[$protocol] = self::$clientClosures[$protocol]();
      unset(self::$clientClosures[$protocol]);
    }
    return self::$clients[$protocol];
  }

  public static function unregister($protocol = null)
  {
    $protocol = $protocol ?: self::DEFAULT_PROTOCOL;
    stream_wrapper_unregister($protocol);
    unset(self::$clients[$protocol], self::$clientClosures[$protocol]);
  }

it would be possible to register a closure that will be executed only when any gs://bucketname/path/filename path is actually accessed and not before.

This became evident when using profiler mode in our deployment for simple ping/pong API endpoint and tracking what parts of code consume unneeded overhead.

In PHP 8.4+ it will be possible to use lazy ghost or proxy objects, but we are still stuck at 8.3 for a while.

Currently we implemented custom-made stream wrapper to achieve that closure-creation approach but possibly would be better to have it natively in the storage library.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions