buildAsset :: Handle -> AssetId -> AssetDefinition -> IO ()
buildAsset h aId ad = do
    Builder src depSet cont fp <- createBuilder ad h aId

    eitherResolvedDeps <- require h depSet
    case eitherResolvedDeps of
        Left e -> failBuild h aId e

        Right resolvedDeps -> do
            let sourceDeps = M.map publicIdentifier resolvedDeps

            -- First check if we actually need to rebuild the asset. If the source
            -- fingerprint is still the same then we can skip directly to 'Completed'.
            needsRebuild <- atomically $ do
                s <- readTVar (state h)
                return $ case M.lookup aId (assets s) of
                    Just (AssetRuntimeState _ _ _ (Just (sfp, srd)) (Just _)) -> sfp /= fp || sourceDeps /= srd
                    _                                                         -> True

            -- Eagerly update the metadata, even if we don't have to rebuild the asset.
            -- When deciding whether to rebuild the asset or not, the only thing that
            -- matters is the fingerprint. But the builder may have an updated or more
            -- accurate set of dependencies now, and we do want to update that.
            updateMetadata h aId src depSet fp sourceDeps


            if not needsRebuild
                then do
                    logMessage h aId $ "Skip"

                    now <- getCurrentTime

                    let diff (Building t0) = diffUTCTime now t0
                        diff _             = fromIntegral (0 :: Int)

                    adjustAssetRuntimeState h aId $ \ars ->
                        ars { arsState = Completed (diff $ arsState ars) }

                else do
                    -- logger lock $ "Got all dependencies of " ++ show aId
                    -- logger lock $ resolvedDeps
                    case cont (M.map publicIdentifier resolvedDeps) of
                        Left e -> failBuild h aId e
                        Right result1@(Result pub _) -> do
                            let result = result1 { publicIdentifier = transformPublicIdentifier ad pub }
                            -- logger lock $ "Pub: " ++ (publicIdentifier result)
                            -- logger lock $ res

                            atomically $ writeTQueue (emitStream h) $ emitResult ad h aId result
                            finishBuilding h aId result
buildAsset :: Handle -> AssetId -> AssetDefinition -> IO ()
buildAsset h aId ad = do
    Builder src depSet cont fp <- createBuilder ad h aId

    eitherResolvedDeps <- require h depSet
    case eitherResolvedDeps of
        Left e -> failBuild h aId e

        Right resolvedDeps -> do
            let sourceDeps = M.map publicIdentifier resolvedDeps

            -- First check if we actually need to rebuild the asset. If the source
            -- fingerprint is still the same then we can skip directly to 'Completed'.
            needsRebuild <- atomically $ do
                s <- readTVar (state h)
                return $ case M.lookup aId (assets s) of
                    Just (AssetRuntimeState _ _ _ (Just (sfp, srd)) (Just _)) -> sfp /= fp || sourceDeps /= srd
                    _                                                         -> True

            -- Eagerly update the metadata, even if we don't have to rebuild the asset.
            -- When deciding whether to rebuild the asset or not, the only thing that
            -- matters is the fingerprint. But the builder may have an updated or more
            -- accurate set of dependencies now, and we do want to update that.
            updateMetadata h aId src depSet fp sourceDeps


            if not needsRebuild
                then do
                    logMessage h aId $ "Skip"

                    now <- getCurrentTime

                    let diff (Building t0) = diffUTCTime now t0
                        diff _             = fromIntegral (0 :: Int)

                    adjustAssetRuntimeState h aId $ \ars ->
                        ars { arsState = Completed (diff $ arsState ars) }

                else do
                    -- logger lock $ "Got all dependencies of " ++ show aId
                    -- logger lock $ resolvedDeps
                    case cont (M.map publicIdentifier resolvedDeps) of
                        Left e -> failBuild h aId e
                        Right result1@(Result pub _) -> do
                            let result = result1 { publicIdentifier = transformPublicIdentifier ad pub }
                            -- logger lock $ "Pub: " ++ (publicIdentifier result)
                            -- logger lock $ res

                            atomically $ writeTQueue (emitStream h) $ emitResult ad h aId result
                            finishBuilding h aId result
buildAsset h aId ad = do
    Builder src depSet cont fp <- createBuilder ad h aId

    eitherResolvedDeps <- require h depSet
    case eitherResolvedDeps of
        Left e -> failBuild h aId e

        Right resolvedDeps -> do
            let sourceDeps = M.map publicIdentifier resolvedDeps

            -- First check if we actually need to rebuild the asset. If the source
            -- fingerprint is still the same then we can skip directly to 'Completed'.
            needsRebuild <- atomically $ do
                s <- readTVar (state h)
                return $ case M.lookup aId (assets s) of
                    Just (AssetRuntimeState _ _ _ (Just (sfp, srd)) (Just _)) -> sfp /= fp || sourceDeps /= srd
                    _                                                         -> True

            -- Eagerly update the metadata, even if we don't have to rebuild the asset.
            -- When deciding whether to rebuild the asset or not, the only thing that
            -- matters is the fingerprint. But the builder may have an updated or more
            -- accurate set of dependencies now, and we do want to update that.
            updateMetadata h aId src depSet fp sourceDeps


            if not needsRebuild
                then do
                    logMessage h aId $ "Skip"

                    now <- getCurrentTime

                    let diff (Building t0) = diffUTCTime now t0
                        diff _             = fromIntegral (0 :: Int)

                    adjustAssetRuntimeState h aId $ \ars ->
                        ars { arsState = Completed (diff $ arsState ars) }

                else do
                    -- logger lock $ "Got all dependencies of " ++ show aId
                    -- logger lock $ resolvedDeps
                    case cont (M.map publicIdentifier resolvedDeps) of
                        Left e -> failBuild h aId e
                        Right result1@(Result pub _) -> do
                            let result = result1 { publicIdentifier = transformPublicIdentifier ad pub }
                            -- logger lock $ "Pub: " ++ (publicIdentifier result)
                            -- logger lock $ res

                            atomically $ writeTQueue (emitStream h) $ emitResult ad h aId result
                            finishBuilding h aId result