code: func (nodeInfo *NodeInfo) taskFailed(ctx context.Context, t *api.Task) {
  	expired := 0
  	now := time.Now()
  
  	if now.Sub(nodeInfo.lastCleanup) >= monitorFailures {
  		nodeInfo.cleanupFailures(now)
  	}
  
  	versionedService := versionedService{serviceID: t.ServiceID}
  	if t.SpecVersion != nil {
  		versionedService.specVersion = *t.SpecVersion
  	}
  
  	for _, timestamp := range nodeInfo.recentFailures[versionedService] {
  		if now.Sub(timestamp) < monitorFailures {
  			break
  		}
  		expired++
  	}
  
  	if len(nodeInfo.recentFailures[versionedService])-expired == maxFailures-1 {
  		log.G(ctx).Warnf("underweighting node %s for service %s because it experienced %d failures or rejections within %s", nodeInfo.ID, t.ServiceID, maxFailures, monitorFailures.String())
  	}
  
  	nodeInfo.recentFailures[versionedService] = append(nodeInfo.recentFailures[versionedService][expired:], now)
  }
docs: // taskFailed records a task failure from a given service.