|
| 1 | +module Share.BackgroundJobs.Diffs.ContributionDiffs (worker) where |
| 2 | + |
| 3 | +import Control.Lens |
| 4 | +import Control.Monad.Except (ExceptT (..), runExceptT) |
| 5 | +import Ki.Unlifted qualified as Ki |
| 6 | +import Share.BackgroundJobs.Diffs.Queries qualified as DQ |
| 7 | +import Share.BackgroundJobs.Errors (reportError) |
| 8 | +import Share.BackgroundJobs.Monad (Background) |
| 9 | +import Share.BackgroundJobs.Workers (newWorker) |
| 10 | +import Share.Branch (Branch (..)) |
| 11 | +import Share.Codebase qualified as Codebase |
| 12 | +import Share.Contribution (Contribution (..)) |
| 13 | +import Share.IDs |
| 14 | +import Share.Metrics qualified as Metrics |
| 15 | +import Share.NamespaceDiffs (NamespaceDiffError (MissingEntityError)) |
| 16 | +import Share.Postgres qualified as PG |
| 17 | +import Share.Postgres.Contributions.Queries qualified as ContributionsQ |
| 18 | +import Share.Postgres.Queries qualified as Q |
| 19 | +import Share.Prelude |
| 20 | +import Share.Utils.Logging qualified as Logging |
| 21 | +import Share.Web.Authorization qualified as AuthZ |
| 22 | +import Share.Web.Errors (EntityMissing (..), ErrorID (..)) |
| 23 | +import Share.Web.Share.Diffs.Impl qualified as Diffs |
| 24 | +import Unison.Debug qualified as Debug |
| 25 | +import UnliftIO.Concurrent qualified as UnliftIO |
| 26 | + |
| 27 | +pollingIntervalSeconds :: Int |
| 28 | +pollingIntervalSeconds = 10 |
| 29 | + |
| 30 | +worker :: Ki.Scope -> Background () |
| 31 | +worker scope = do |
| 32 | + authZReceipt <- AuthZ.backgroundJobAuthZ |
| 33 | + newWorker scope "diffs:contributions" $ forever do |
| 34 | + processDiffs authZReceipt >>= \case |
| 35 | + Left e -> reportError e |
| 36 | + Right _ -> pure () |
| 37 | + liftIO $ UnliftIO.threadDelay $ pollingIntervalSeconds * 1000000 |
| 38 | + |
| 39 | +processDiffs :: AuthZ.AuthZReceipt -> Background (Either NamespaceDiffError ()) |
| 40 | +processDiffs authZReceipt = Metrics.recordContributionDiffDuration . runExceptT $ do |
| 41 | + Debug.debugLogM Debug.Temp "Background: Getting contributions to be diffed" |
| 42 | + mayContributionId <- PG.runTransactionMode PG.ReadCommitted PG.ReadWrite $ do |
| 43 | + DQ.claimContributionToDiff |
| 44 | + Debug.debugM Debug.Temp "Background: contribution to be diffed: " mayContributionId |
| 45 | + for_ mayContributionId (diffContribution authZReceipt) |
| 46 | + case mayContributionId of |
| 47 | + Just contributionId -> do |
| 48 | + Logging.textLog ("Recomputed contribution diff: " <> tShow contributionId) |
| 49 | + & Logging.withTag ("contribution-id", tShow contributionId) |
| 50 | + & Logging.withSeverity Logging.Info |
| 51 | + & Logging.logMsg |
| 52 | + -- Keep processing releases until we run out of them. |
| 53 | + either throwError pure =<< lift (processDiffs authZReceipt) |
| 54 | + Nothing -> pure () |
| 55 | + |
| 56 | +diffContribution :: AuthZ.AuthZReceipt -> ContributionId -> ExceptT NamespaceDiffError Background () |
| 57 | +diffContribution authZReceipt contributionId = do |
| 58 | + ( project, |
| 59 | + newBranch@Branch {causal = newBranchCausalId}, |
| 60 | + oldBranch@Branch {causal = oldBranchCausalId} |
| 61 | + ) <- ExceptT $ PG.tryRunTransaction $ do |
| 62 | + Contribution {sourceBranchId = newBranchId, targetBranchId = oldBranchId, projectId} <- ContributionsQ.contributionById contributionId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "contribution:missing") "Contribution not found") |
| 63 | + project <- Q.projectById projectId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "project:missing") "Project not found") |
| 64 | + newBranch <- Q.branchById newBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Source branch not found") |
| 65 | + oldBranch <- Q.branchById oldBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Target branch not found") |
| 66 | + pure (project, newBranch, oldBranch) |
| 67 | + let oldCodebase = Codebase.codebaseForProjectBranch authZReceipt project oldBranch |
| 68 | + let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch |
| 69 | + -- This method saves the diff so it'll be there when we need it, so we don't need to do anything with it. |
| 70 | + _ <- Diffs.diffCausals authZReceipt (oldCodebase, oldBranchCausalId) (newCodebase, newBranchCausalId) |
| 71 | + pure () |
0 commit comments