github.com/code-to-go/safepool.lib@v0.0.0-20221205180519-ee25e63c226e/transport/lock.go (about)

     1  package transport
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/code-to-go/safepool.lib/core"
     7  
     8  	"github.com/godruoyi/go-snowflake"
     9  )
    10  
    11  type lockFileContent struct {
    12  	Id   uint64
    13  	Span time.Duration
    14  }
    15  
    16  func waitLock(e Exchanger, name string) {
    17  	var c lockFileContent
    18  	var err error
    19  	var id uint64
    20  	var shot time.Time
    21  
    22  	for shot.IsZero() && time.Since(shot) > c.Span {
    23  		id = c.Id
    24  		err = ReadJSON(e, name, &c, nil)
    25  		if err != nil {
    26  			return
    27  		}
    28  		if c.Id != id {
    29  			shot = time.Now()
    30  		}
    31  		time.Sleep(time.Second)
    32  	}
    33  }
    34  
    35  func LockFile(e Exchanger, name string, span time.Duration) (uint64, error) {
    36  	var c lockFileContent
    37  	id := snowflake.ID()
    38  	for c.Id != id {
    39  		waitLock(e, name)
    40  
    41  		err := WriteJSON(e, name, lockFileContent{
    42  			Id:   id,
    43  			Span: span,
    44  		}, nil)
    45  		if core.IsErr(err, "cannot write lock file %s: %v", name) {
    46  			return 0, err
    47  		}
    48  		time.Sleep(time.Second)
    49  		err = ReadJSON(e, name, &c, nil)
    50  		if core.IsErr(err, "cannot read lock file %s: %v", name) {
    51  			return 0, err
    52  		}
    53  	}
    54  	return id, nil
    55  }
    56  
    57  func UnlockFile(e Exchanger, name string, id uint64) {
    58  	var c lockFileContent
    59  	_ = ReadJSON(e, name, &c, nil)
    60  	if c.Id == id {
    61  		e.Delete(name)
    62  	}
    63  }