github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/lidar/scanner.go (about) 1 package lidar 2 3 import ( 4 "context" 5 "strconv" 6 "sync" 7 8 "code.cloudfoundry.org/lager/lagerctx" 9 "github.com/pf-qiu/concourse/v6/atc/db" 10 "github.com/pf-qiu/concourse/v6/atc/metric" 11 "github.com/pf-qiu/concourse/v6/atc/util" 12 "github.com/pf-qiu/concourse/v6/tracing" 13 ) 14 15 func NewScanner(checkFactory db.CheckFactory) *scanner { 16 return &scanner{ 17 checkFactory: checkFactory, 18 } 19 } 20 21 type scanner struct { 22 checkFactory db.CheckFactory 23 } 24 25 func (s *scanner) Run(ctx context.Context) error { 26 logger := lagerctx.FromContext(ctx) 27 28 spanCtx, span := tracing.StartSpan(ctx, "scanner.Run", nil) 29 defer span.End() 30 31 logger.Info("start") 32 defer logger.Info("end") 33 34 resources, err := s.checkFactory.Resources() 35 if err != nil { 36 logger.Error("failed-to-get-resources", err) 37 return err 38 } 39 40 resourceTypes, err := s.checkFactory.ResourceTypes() 41 if err != nil { 42 logger.Error("failed-to-get-resource-types", err) 43 return err 44 } 45 46 waitGroup := new(sync.WaitGroup) 47 resourceTypesChecked := &sync.Map{} 48 49 for _, resource := range resources { 50 waitGroup.Add(1) 51 52 go func(resource db.Resource, resourceTypes db.ResourceTypes) { 53 defer func() { 54 err := util.DumpPanic(recover(), "scanning resource %d", resource.ID()) 55 if err != nil { 56 logger.Error("panic-in-scanner-run", err) 57 } 58 }() 59 defer waitGroup.Done() 60 61 s.check(spanCtx, resource, resourceTypes, resourceTypesChecked) 62 }(resource, resourceTypes) 63 } 64 65 waitGroup.Wait() 66 67 return nil 68 } 69 70 func (s *scanner) check(ctx context.Context, checkable db.Checkable, resourceTypes db.ResourceTypes, resourceTypesChecked *sync.Map) { 71 logger := lagerctx.FromContext(ctx) 72 73 spanCtx, span := tracing.StartSpan(ctx, "scanner.check", tracing.Attrs{ 74 "team": checkable.TeamName(), 75 "pipeline": checkable.PipelineName(), 76 "resource": checkable.Name(), 77 "type": checkable.Type(), 78 "resource_config_scope_id": strconv.Itoa(checkable.ResourceConfigScopeID()), 79 }) 80 defer span.End() 81 82 parentType, found := resourceTypes.Parent(checkable) 83 if found { 84 if _, exists := resourceTypesChecked.LoadOrStore(parentType.ID(), true); !exists { 85 // only create a check for resource type if it has not been checked yet 86 s.check(spanCtx, parentType, resourceTypes, resourceTypesChecked) 87 } 88 } 89 90 version := checkable.CurrentPinnedVersion() 91 92 _, created, err := s.checkFactory.TryCreateCheck(lagerctx.NewContext(spanCtx, logger), checkable, resourceTypes, version, false) 93 if err != nil { 94 logger.Error("failed-to-create-check", err) 95 return 96 } 97 98 if !created { 99 logger.Debug("check-already-exists") 100 } else { 101 metric.Metrics.ChecksEnqueued.Inc() 102 } 103 }