public List<String> getFeedComputeLocations(FeedId feedId) {
   List<IFeedJoint> feedJoints = feedPipeline.get(feedId);
   for (IFeedJoint joint : feedJoints) {
     if (joint.getFeedJointKey().getFeedId().equals(feedId)) {
       return connectJobInfos.get(joint.getProvider()).getComputeLocations();
     }
   }
   return null;
 }
  public synchronized void submitFeedConnectionRequest(
      IFeedJoint feedJoint, final FeedConnectionRequest request) throws Exception {
    List<String> locations = null;
    switch (feedJoint.getType()) {
      case INTAKE:
        FeedIntakeInfo intakeInfo = intakeJobInfos.get(feedJoint.getOwnerFeedId());
        locations = intakeInfo.getIntakeLocation();
        break;
      case COMPUTE:
        FeedConnectionId connectionId = feedJoint.getProvider();
        FeedConnectJobInfo cInfo = connectJobInfos.get(connectionId);
        locations = cInfo.getComputeLocations();
        break;
    }

    SubscribeFeedWork work = new SubscribeFeedWork(locations.toArray(new String[] {}), request);
    FeedWorkManager.INSTANCE.submitWork(
        work, new SubscribeFeedWork.FeedSubscribeWorkEventListener());
  }
  private void handleCollectJobStartMessage(FeedConnectJobInfo cInfo)
      throws RemoteException, ACIDException {
    // set locations of feed sub-operations (intake, compute, store)
    setLocations(cInfo);

    // activate joints
    List<IFeedJoint> joints = feedPipeline.get(cInfo.getConnectionId().getFeedId());
    for (IFeedJoint joint : joints) {
      if (joint.getProvider().equals(cInfo.getConnectionId())) {
        joint.setState(State.ACTIVE);
        if (joint.getType().equals(IFeedJoint.FeedJointType.COMPUTE)) {
          cInfo.setComputeFeedJoint(joint);
        }
      }
    }
    cInfo.setState(FeedJobState.ACTIVE);

    // register activity in metadata
    registerFeedActivity(cInfo);
    // notify event listeners
    notifyFeedEventSubscribers(cInfo, FeedLifecycleEvent.FEED_COLLECT_STARTED);
  }