shipBlocks runs shipping for all users.
(ctx context.Context, allowed *users.AllowedTenants)
| 3170 | |
| 3171 | // shipBlocks runs shipping for all users. |
| 3172 | func (i *Ingester) shipBlocks(ctx context.Context, allowed *users.AllowedTenants) { |
| 3173 | // Do not ship blocks if the ingester is PENDING or JOINING. It's |
| 3174 | // particularly important for the JOINING state because there could |
| 3175 | // be a blocks transfer in progress (from another ingester) and if we |
| 3176 | // run the shipper in such state we could end up with race conditions. |
| 3177 | if i.lifecycler != nil { |
| 3178 | if ingesterState := i.lifecycler.GetState(); ingesterState == ring.PENDING || ingesterState == ring.JOINING { |
| 3179 | level.Info(logutil.WithContext(ctx, i.logger)).Log("msg", "TSDB blocks shipping has been skipped because of the current ingester state", "state", ingesterState) |
| 3180 | return |
| 3181 | } |
| 3182 | } |
| 3183 | |
| 3184 | // Number of concurrent workers is limited in order to avoid to concurrently sync a lot |
| 3185 | // of tenants in a large cluster. |
| 3186 | _ = concurrency.ForEachUser(ctx, i.getTSDBUsers(), i.cfg.BlocksStorageConfig.TSDB.ShipConcurrency, func(ctx context.Context, userID string) error { |
| 3187 | if !allowed.IsAllowed(userID) { |
| 3188 | return nil |
| 3189 | } |
| 3190 | |
| 3191 | // Get the user's DB. If the user doesn't exist, we skip it. |
| 3192 | userDB, err := i.getTSDB(userID) |
| 3193 | if err != nil || userDB == nil || userDB.shipper == nil { |
| 3194 | return nil |
| 3195 | } |
| 3196 | |
| 3197 | if userDB.deletionMarkFound.Load() { |
| 3198 | return nil |
| 3199 | } |
| 3200 | |
| 3201 | if time.Since(time.Unix(userDB.lastDeletionMarkCheck.Load(), 0)) > cortex_tsdb.DeletionMarkCheckInterval { |
| 3202 | // Even if check fails with error, we don't want to repeat it too often. |
| 3203 | userDB.lastDeletionMarkCheck.Store(time.Now().Unix()) |
| 3204 | |
| 3205 | deletionMarkExists, err := users.TenantDeletionMarkExists(ctx, i.TSDBState.bucket, userID) |
| 3206 | if err != nil { |
| 3207 | // If we cannot check for deletion mark, we continue anyway, even though in production shipper will likely fail too. |
| 3208 | // This however simplifies unit tests, where tenant deletion check is enabled by default, but tests don't setup bucket. |
| 3209 | level.Warn(logutil.WithContext(ctx, i.logger)).Log("msg", "failed to check for tenant deletion mark before shipping blocks", "user", userID, "err", err) |
| 3210 | } else if deletionMarkExists { |
| 3211 | userDB.deletionMarkFound.Store(true) |
| 3212 | |
| 3213 | level.Info(logutil.WithContext(ctx, i.logger)).Log("msg", "tenant deletion mark exists, not shipping blocks", "user", userID) |
| 3214 | return nil |
| 3215 | } |
| 3216 | } |
| 3217 | |
| 3218 | // Run the shipper's Sync() to upload unshipped blocks. Make sure the TSDB state is active, in order to |
| 3219 | // avoid any race condition with closing idle TSDBs. |
| 3220 | if !userDB.casState(active, activeShipping) { |
| 3221 | level.Info(logutil.WithContext(ctx, i.logger)).Log("msg", "shipper skipped because the TSDB is not active", "user", userID) |
| 3222 | return nil |
| 3223 | } |
| 3224 | defer userDB.casState(activeShipping, active) |
| 3225 | |
| 3226 | if idxs, err := bucketindex.ReadSyncStatus(ctx, i.TSDBState.bucket, userID, logutil.WithContext(ctx, i.logger)); err == nil { |
| 3227 | // Skip blocks shipping if the bucket index failed to sync due to CMK errors. |
| 3228 | if idxs.Status == bucketindex.CustomerManagedKeyError { |
| 3229 | level.Info(logutil.WithContext(ctx, i.logger)).Log("msg", "skipping shipping blocks due CustomerManagedKeyError", "user", userID) |