github.com/diggerhq/digger/libs@v0.0.0-20240604170430-9d61cdf01cc5/locking/gcp/gcp_lock.go (about)

     1  package gcp
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"strconv"
     8  	"time"
     9  
    10  	"cloud.google.com/go/storage"
    11  )
    12  
    13  type GoogleStorageLock struct {
    14  	Client  *storage.Client
    15  	Bucket  *storage.BucketHandle
    16  	Context context.Context
    17  }
    18  
    19  func (googleLock *GoogleStorageLock) Lock(transactionId int, resource string) (bool, error) {
    20  	now := time.Now().Format(time.RFC3339)
    21  	fileName := resource
    22  
    23  	wc := googleLock.Bucket.Object(fileName).NewWriter(googleLock.Context)
    24  	wc.ContentType = "text/plain"
    25  	wc.Metadata = map[string]string{
    26  		"LockId":    strconv.Itoa(transactionId),
    27  		"CreatedAt": now,
    28  	}
    29  
    30  	bucketAttrs, err := googleLock.Bucket.Attrs(googleLock.Context)
    31  	if err != nil {
    32  		log.Printf("failed to get bucket attributes: %v\n", err)
    33  	}
    34  	bucketName := bucketAttrs.Name
    35  
    36  	if err := wc.Close(); err != nil {
    37  		log.Printf("createFile: unable to close bucket %q, file %q: %v\n", bucketName, fileName, err)
    38  	}
    39  	return true, nil
    40  }
    41  
    42  func (googleLock *GoogleStorageLock) Unlock(resource string) (bool, error) {
    43  	fileName := resource
    44  
    45  	existingLockTransactionId, err := googleLock.GetLock(resource)
    46  	if err != nil {
    47  		log.Printf("failed to get lock: %v\n", err)
    48  	}
    49  	if existingLockTransactionId == nil {
    50  		return false, nil
    51  	}
    52  
    53  	fileObject := googleLock.Bucket.Object(fileName)
    54  	err = fileObject.Delete(googleLock.Context)
    55  	if err != nil {
    56  		return false, fmt.Errorf("failed to delete lock file: %v\n", err)
    57  	}
    58  
    59  	return true, nil
    60  }
    61  
    62  func (googleLock *GoogleStorageLock) GetLock(resource string) (*int, error) {
    63  	fileName := resource
    64  	fileObject := googleLock.Bucket.Object(fileName)
    65  	fileAttrs, err := fileObject.Attrs(googleLock.Context)
    66  	if err != nil {
    67  		// TODO: not sure if it's the best way to handle it
    68  		if err.Error() == "storage: object doesn't exist" {
    69  			return nil, nil
    70  		}
    71  		return nil, err
    72  	}
    73  	fileMetadata := fileAttrs.Metadata
    74  	lockIdStr := fileMetadata["LockId"]
    75  	transactionId, err := strconv.Atoi(lockIdStr)
    76  	if err != nil {
    77  		log.Printf("failed to parse LockId in object's metadata: %v\n", err)
    78  	}
    79  	return &transactionId, nil
    80  }
    81  
    82  func GetGoogleStorageClient() (context.Context, *storage.Client) {
    83  	ctx := context.Background()
    84  
    85  	client, err := storage.NewClient(ctx)
    86  	if err != nil {
    87  		log.Fatalf("Failed to create Google Storage client: %v", err)
    88  	}
    89  	return ctx, client
    90  }