【问题标题】:What is the correct way to gracefully fail Symfony service factory?Symfony 服务工厂正常失败的正确方法是什么?
【发布时间】:2018-11-15 16:00:07
【问题描述】:

Symfony's documentation for service factories 解释了如何允许服务容器使用工​​厂实例化服务,但没有解释当创建失败时推荐的最佳实践是什么,即当服务由于某种原因不可用时。

例如;想象一个 Redis 内存缓存服务。在工厂类中,您有一个将实例化并返回 Redis 客户端对象的方法;

public function createRedisClient() {
  $redis = new \Redis();
  $connectionResult = $redis->connect($host, $port);

  return $redis;
}

如果 Redis 服务器暂时不可用,我希望能够优雅地退回到另一个解决方案来存储我们拥有的任何数据,如果工厂返回 null,抛出某种特定类型的异常,或者根本不关心可用性?

【问题讨论】:

  • 假设您希望连接几乎总是可用,只需抛出一个异常。如果你真的想要一个优雅的降级,那么做链的事情并返回某种假缓存,如下面的答案所示。

标签: php symfony service containers graceful-degradation


【解决方案1】:

如果您想要一个“后备”解决方案,最佳实践是将这些服务分组到一个公共接口下,而不是尝试像“责任链”一样一次实例化一个:首先可以实例化,然后返回。 当然,在您的客户端中,您将使用该界面,因此对于“客户端开发人员”而言,此过程将非常简单。

获得这个的最好方法是拥有类似SessionStorageFactory(所以是通用的)的东西,您可以在其中“注册”所有具体工厂(RedisFactory,...,DefaultSessionStorageFactory)并尝试在一次。

当然缺点是,如果您可能需要属性的“超集”(如 hostport 等),这对所有工厂都无用,但需要参数的具体工厂除外。

【讨论】:

    【解决方案2】:

    你可以使用 PHP 的 is_object 方法:

        public function createRedisClient() {
          $redis = new \Redis();
          $connectionResult = $redis->connect($host, $port);
          if (!is_object($redis)) {
            return false;
          }
          return $redis;
    }
    

    返回值:

    如果 var 是 对象,则返回 TRUE,否则返回 FALSE。

    参考:PHP is_object

    【讨论】:

    • 我不认为这是正确的,因为$redis 始终是一个对象,无论它是否成功连接到 Redis 服务器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多