nolint:gocyclo
(ctx context.Context, project *types.Project, dependant string, dependencies types.DependsOnConfig, containers Containers, timeout time.Duration)
| 155 | |
| 156 | //nolint:gocyclo |
| 157 | func (s *composeService) waitDependencies(ctx context.Context, project *types.Project, dependant string, dependencies types.DependsOnConfig, containers Containers, timeout time.Duration) error { |
| 158 | if timeout > 0 { |
| 159 | withTimeout, cancelFunc := context.WithTimeout(ctx, timeout) |
| 160 | defer cancelFunc() |
| 161 | ctx = withTimeout |
| 162 | } |
| 163 | eg, ctx := errgroup.WithContext(ctx) |
| 164 | for dep, config := range dependencies { |
| 165 | if shouldWait, err := shouldWaitForDependency(dep, config, project); err != nil { |
| 166 | return err |
| 167 | } else if !shouldWait { |
| 168 | continue |
| 169 | } |
| 170 | |
| 171 | waitingFor := containers.filter(isService(dep), isNotOneOff) |
| 172 | s.events.On(containerEvents(waitingFor, waiting)...) |
| 173 | if len(waitingFor) == 0 { |
| 174 | if config.Required { |
| 175 | return fmt.Errorf("%s is missing dependency %s", dependant, dep) |
| 176 | } |
| 177 | logrus.Warnf("%s is missing dependency %s", dependant, dep) |
| 178 | continue |
| 179 | } |
| 180 | |
| 181 | eg.Go(func() error { |
| 182 | ticker := time.NewTicker(500 * time.Millisecond) |
| 183 | defer ticker.Stop() |
| 184 | for { |
| 185 | select { |
| 186 | case <-ticker.C: |
| 187 | case <-ctx.Done(): |
| 188 | return nil |
| 189 | } |
| 190 | switch config.Condition { |
| 191 | case ServiceConditionRunningOrHealthy: |
| 192 | isHealthy, err := s.isServiceHealthy(ctx, waitingFor, true) |
| 193 | if err != nil { |
| 194 | if !config.Required { |
| 195 | s.events.On(containerReasonEvents(waitingFor, skippedEvent, |
| 196 | fmt.Sprintf("optional dependency %q is not running or is unhealthy", dep))...) |
| 197 | logrus.Warnf("optional dependency %q is not running or is unhealthy: %s", dep, err.Error()) |
| 198 | return nil |
| 199 | } |
| 200 | return err |
| 201 | } |
| 202 | if isHealthy { |
| 203 | s.events.On(containerEvents(waitingFor, healthy)...) |
| 204 | return nil |
| 205 | } |
| 206 | case types.ServiceConditionHealthy: |
| 207 | isHealthy, err := s.isServiceHealthy(ctx, waitingFor, false) |
| 208 | if err != nil { |
| 209 | if !config.Required { |
| 210 | s.events.On(containerReasonEvents(waitingFor, skippedEvent, |
| 211 | fmt.Sprintf("optional dependency %q failed to start", dep))...) |
| 212 | logrus.Warnf("optional dependency %q failed to start: %s", dep, err.Error()) |
| 213 | return nil |
| 214 | } |