Go equivalent of laravel redis lock

I want the multiple requests of a same API for a specific users to be executed sequentially. If 3 requests of same API for a users comes together then the 1st request should be processed immediately and the 2nd and 3rd request should be put on wait. 2nd request should start execution only after the completion of 1st request. 3rd request should start execution only after the completion of 2nd request and so on.

For example, user making 3 scan and pay back to back

Request R1 POST create-txn/user001  {amount : 50}
Request R2 POST create-txn/user001  {amount : 100}
Request R3 POST create-txn/user001  {amount : 10}

In Laravel we handle like:

use Illuminate\Support\Facades\Cache;
use Illuminate\Contracts\Cache\LockTimeoutException;


function createTxn()
{
    $lock = Cache::lock("create_txn_" . $postdata['user_id'] . '_lock', 30);
    try {
        $lock->block(5); // Lock acquired after waiting maximum of 5 seconds..

        // code for creating txn
    } catch (LockTimeoutException $e) {
        throw new ServiceErrorException('create txn api LockTimeout Exception', 105);
    } finally {
        optional($lock)->release();
    }
}

I want the Go equivalent code for the above logic. I tried bsm/redislock and mutex but I did not get the expected result. Need example in Go.

I tried below code but didnt work also

package main
import (
  "context"
  "fmt"
  "time"

  "github.com/bsm/redislock"
  "github.com/redis/go-redis/v9"
   "github.com/gin-gonic/gin"
)

func main() {

router := gin.Default()

    router.GET("/test/:id", getTestByID)
    router.Run("localhost:8080")
    }
    
    

func getTestByID(c *gin.Context) {

    id := c.Param("id")
    lockKey := "test_"+id;
    fmt.Println("recieved", id, lockKey)
	// Connect to redis.
	client := redis.NewClient(&redis.Options{
		Network:	"tcp",
		Addr:		"127.0.0.1:6379",
		DB:      9,
	})
	defer client.Close()

	// Create a new lock client.
	locker := redislock.New(client)

	ctx := context.Background()

	// Try to obtain lock.
	lock, _ := locker.Obtain(ctx, lockKey, 5*time.Second, nil)
	


	// Don't forget to defer Release.
	defer lock.Release(ctx)
	fmt.Println("I have a lock!")

	// Sleep and check the remaining TTL.
	
	time.Sleep(4*time.Second)
	fmt.Println(5*time.Second)
	
	//lock.Release(ctx)

}

When called localhost:8080/test/4 multiple times first print can be executed immediately for all the calls but 2nd and 3rd print statements should be delayed due to lock for the 2nd request onwards

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.