private function loadServices(DrydockBlueprint $blueprint)
 {
     if (!$this->services) {
         $service_phids = $blueprint->getFieldValue('almanacServicePHIDs');
         if (!$service_phids) {
             throw new Exception(pht('This blueprint ("%s") does not define any Almanac Service PHIDs.', $blueprint->getBlueprintName()));
         }
         $viewer = PhabricatorUser::getOmnipotentUser();
         $services = id(new AlmanacServiceQuery())->setViewer($viewer)->withPHIDs($service_phids)->withServiceClasses($this->getAlmanacServiceClasses())->needBindings(true)->execute();
         $services = mpull($services, null, 'getPHID');
         if (count($services) != count($service_phids)) {
             $missing_phids = array_diff($service_phids, array_keys($services));
             throw new Exception(pht('Some of the Almanac Services defined by this blueprint ' . 'could not be loaded. They may be invalid, no longer exist, ' . 'or be of the wrong type: %s.', implode(', ', $missing_phids)));
         }
         $this->services = $services;
     }
     return $this->services;
 }
 /**
  * Get the effective concurrent resource limit for this blueprint.
  *
  * @param DrydockBlueprint Blueprint to get the limit for.
  * @return int|null Limit, or `null` for no limit.
  */
 protected function getConcurrentResourceLimit(DrydockBlueprint $blueprint)
 {
     if ($this->shouldUseConcurrentResourceLimit()) {
         $limit = $blueprint->getFieldValue('allocator.limit');
         $limit = (int) $limit;
         if ($limit > 0) {
             return $limit;
         } else {
             return null;
         }
     }
     return null;
 }