locker

package module
v0.0.0-...-fc7c8a0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 5, 2022 License: Apache-2.0 Imports: 3 Imported by: 0

README

locker

Description

locker provides an interface and implementations of named lock for exclusivity control between processes and threads.

func ExampleLocker() {
	// setup *sql.DB
	db := setupPostgres()
	defer db.Close()

	// Acquire the lock by specified key. (Using PostgreSQL pg_advisory_lock)
	key := randHex(16)
	locker := postgres.NewLocker(db)
	lock, err := locker.Get(context.Background(), key)
	if err != nil {
		panic(fmt.Sprintf("failed to acquire: %+v", err))
	}
	// Releases the lock at the end of the function
	defer lock.Release()
	fmt.Println("lock acquired")

	// The same key will be blocked until the lock is released
	done := make(chan interface{})
	go func() {
		defer close(done)
		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
		defer cancel()
		lock, err := locker.Get(ctx, key)
		if err != nil {
			if errors.Is(err, context.DeadlineExceeded) {
				return
			}
			panic(fmt.Sprintf("unexpected err: %+v", err))
		}
		lock.Release()
		fmt.Println("unexpected lock acquired")
	}()
	<-done

	// Output:
	// lock acquired
}

Lock implementations

Currently provides following implementations.

  • postgres.Locker
    • postgres.Locker provides a simple lock mechanism using PostgreSQL pg_advisory_lock
    • Recommend that using the pgx PostgreSQL Driver
  • mysql.Locker
    • mysql.Locker provides a simple lock mechanism using MySQL GET_LOCK

Installation

$ go get github.com/kei2100/locker

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Lock

type Lock interface {
	// Release releases the acquired named lock object.
	Release()
}

Lock interface represents an acquired named lock object.

type Locker

type Locker interface {
	// Get acquires a lock with the name specified by key.
	// If another session has already acquired a lock with the same name, it blocks until the lock is released or ctx.Done.
	Get(ctx context.Context, key string) (Lock, error)
}

Locker is an interface for acquiring named locks.

Example
package main

import (
	"context"
	"crypto/rand"
	"database/sql"
	"errors"
	"fmt"
	"os"
	"time"

	_ "github.com/jackc/pgx/v4/stdlib" // init driver
	"github.com/kei2100/locker/postgres"
)

func main() {
	// setup *sql.DB
	db := setupPostgres()
	defer db.Close()

	// Acquire the lock by specified key. (Using PostgreSQL pg_advisory_lock)
	key := randHex(16)
	locker := postgres.NewLocker(db)
	lock, err := locker.Get(context.Background(), key)
	if err != nil {
		panic(fmt.Sprintf("failed to acquire: %+v", err))
	}
	// Releases the lock at the end of the function
	defer lock.Release()
	fmt.Println("lock acquired")

	// The same key will be blocked until the lock is released
	done := make(chan interface{})
	go func() {
		defer close(done)
		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
		defer cancel()
		lock, err := locker.Get(ctx, key)
		if err != nil {
			if errors.Is(err, context.DeadlineExceeded) {
				return
			}
			panic(fmt.Sprintf("unexpected err %+v", err))
		}
		lock.Release()
		fmt.Println("unexpected lock acquired")
	}()
	<-done

}

func setupPostgres() *sql.DB {
	user := "develop"
	password := "develop"
	host := "localhost"
	port := os.Getenv("HOST_POSTGRES_PORT")
	if port == "" {
		port = "5432"
	}
	database := "develop"
	dsn := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable",
		user,
		password,
		host,
		port,
		database,
	)
	db, err := sql.Open("pgx", dsn)
	if err != nil {
		panic(err)
	}
	return db
}

func randHex(bytes int) string {
	randBytes := make([]byte, bytes)
	if _, err := rand.Read(randBytes); err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", randBytes)
}
Output:

lock acquired

type Logger

type Logger interface {
	// Printf calls Output to print to the standard logger.
	// Arguments are handled in the manner of fmt.Printf.
	Printf(format string, v ...interface{})

	// Println calls Output to print to the standard logger.
	// Arguments are handled in the manner of fmt.Println.
	Println(v ...interface{})
}

Logger interface

var DefaultLogger Logger = log.New(os.Stderr, "", log.LstdFlags)

DefaultLogger is the default logger used by the Locker implementations

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL