You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: main.go
    path of file: ./repos/cds/contrib/grpcplugins/action/downloadArtifact
    
    the code of the file until where you have to start completion: package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/golang/protobuf/ptypes/empty"
	"github.com/ovh/cds/contrib/grpcplugins"
	"github.com/ovh/cds/engine/worker/pkg/workerruntime"
	"github.com/ovh/cds/sdk"
	"github.com/ovh/cds/sdk/grpcplugin/actionplugin"
)

type runActionDownloadArtifactlugin struct {
	actionplugin.Common
	cacheIntegrations     map[string]sdk.ProjectIntegration
	lockCacheIntegrations *sync.Mutex
}

func main() {
	actPlugin := runActionDownloadArtif
    
func (actPlugin *runActionDownloadArtifactlugin) perform(ctx context.Context, name, path string) error {
	if name == "" {
		grpcplugins.Log("No artifact name specified, downloading all artifacts")
	}

	workDirs, err := grpcplugins.GetWorkerDirectories(ctx, &actPlugin.Common)
	if err != nil {
		return err
	}

	response, err := grpcplugins.GetV2RunResults(ctx, &actPlugin.Common, workerruntime.V2FilterRunResult{Pattern: name, Type: []sdk.V2WorkflowRunResultType{sdk.V2WorkflowRunResultTypeCoverage, sdk.V2WorkflowRunResultTypeGeneric}})
	if err != nil {
		return err
	}

	filteredRunResults := make([]sdk.V2WorkflowRunResult, 0)
	for _, r := range response.RunResults {
		if r.Type == sdk.V2WorkflowRunResultTypeGeneric || r.Type == sdk.V2WorkflowRunResultTypeCoverage {
			filteredRunResults = append(filteredRunResults, r)
		}
	}

	if len(filteredRunResults) == 0 {
		grpcplugins.Log("Unable to find any artifacts for the associated workflow")
	}

	var nbSuccess int
	var hasError bool

	grpcplugins.Logf("Total number of files that will be downloaded: %d", len(response.RunResults))

	for _, r := range filteredRunResults {
		t0 := time.Now()

		switch {
		case r.ArtifactManagerIntegrationName == nil: // download from CDN
			x, destinationFile, n, err := downloadFromCDN(ctx, &actPlugin.Common, r, response.CDNSignature, *workDirs, path)
			if err != nil {
				grpcplugins.Errorf(err.Error())
				hasError = true
				continue
			}
			grpcplugins.Logf("Artifact %q was downloaded to %s (%d bytes downloaded in %.3f seconds).", x.Name, destinationFile, n, time.Since(t0).Seconds())
		case r.ArtifactManagerIntegrationName != nil: // download from artifactory

			// Get integration from the local cache, or from the worker
			actPlugin.lockCacheIntegrations.Lock()
			integ, has := actPlugin.cacheIntegrations[*r.ArtifactManagerIntegrationName]
			if !has {
				integFromWorker, err := grpcplugins.GetIntegrationByName(ctx, &actPlugin.Common, *r.ArtifactManagerIntegrationName)
				if err != nil {
					grpcplugins.Errorf(err.Error())
					hasError = true
					actPlugin.lockCacheIntegrations.Unlock()
					continue
				}
				actPlugin.cacheIntegrations[*r.ArtifactManagerIntegrationName] = *integFromWorker
				integ = *integFromWorker
			}
			actPlugin.lockCacheIntegrations.Unlock()

			x, destinationFile, n, err := downloadFromArtifactory(ctx, &actPlugin.Common, integ, *workDirs, r, path)
			if err != nil {
				grpcplugins.Errorf(err.Error())
				hasError = true
				continue
			}
			grpcplugins.Successf("Artifact %q was downloaded to %s (%d bytes downloaded in %.3f seconds).", x.Name, destinationFile, n, time.Since(t0).Seconds())
		}
		nbSuccess++
	}

	if hasError {
		return errors.New("artifacts download failed")
	}

	grpcplugins.Logf("There were %d artifacts downloaded", nbSuccess)

	return nil
}