Home > Blockchain >  Redis GET returns short write error in Go
Redis GET returns short write error in Go

Time:09-12

I have some code to schedule jobs across processes on a given frequency:

func doMasterInner(ctx context.Context, conn redis.Conn, suffix string, 
    freq time.Duration, op func(context.Contex) error) error {

    key := fmt.Sprintf("myserviced_%s", suffix)
    _, err := redis.Int(conn.Do("GET", key))

    var shouldRun bool
    if err != nil {
        if err != redis.ErrNil {
            return fmt.Errorf("Failed to get %s from Redis, error: %v", key, err)
        }

        shouldRun = true
        if _, err := conn.Do("SETEX", key, int(freq.Seconds()), 0); err != nil {
            return fmt.Errorf("Failed to set timer for %s in Redis, error: %v", key, err)
        }
    }

    if shouldRun {
        return op(ctx)
    }

    return nil
}

However, when I call this code:

pool := &redis.Pool{
    MaxIdle:     3,
    MaxActive:   4,
    Wait:        true,
    IdleTimeout: 240 * time.Second,
    Dial:        func() (redis.Conn, error) { 
        return redis.Dial("tcp", addr, 
            redis.DialPassword(password),
            redis.DialConnectTimeout(5 * time.Second)) 
    },
}

conn := pool.Get()
defer conn.Close()

err := doMasterInner(context.Background(), conn, "assets", time.Hour, 
    func(ctx context.Context) error {
        // do something here
        return nil
    })

fmt.Printf("Error: %v", err)

The print function prints Failed to get myserviced_assets from Redis, error: short write. I'm not sure why this is happening as this error message indicates that it is the GET that is failing. What causes Redis to return a short write message on a GET?

CodePudding user response:

So, this code in and of itself wasn't the issue. The real issue was that I was using this code and calling many instances of doMasterInner concurrently with the same redis.Conn object. Although I'm not exactly sure what caused this issue, my guess is that having multiple threads attempting to write to the same redis.Conn buffer caused the error. Modifying doMasterInner like this fixed the issue:

func doMasterInner(ctx context.Context, conn *redis.Pool, suffix string, 
    freq time.Duration, op func(context.Contex) error) error {

    conn := pool.Get()
    defer conn.Close()

    key := fmt.Sprintf("myserviced_%s", suffix)
    _, err := redis.Int(conn.Do("GET", key))

    var shouldRun bool
    if err != nil {
        if err != redis.ErrNil {
            return fmt.Errorf("Failed to get %s from Redis, error: %v", key, err)
        }

        shouldRun = true
        if _, err := conn.Do("SETEX", key, int(freq.Seconds()), 0); err != nil {
            return fmt.Errorf("Failed to set timer for %s in Redis, error: %v", key, err)
        }
    }

    if shouldRun {
        return op(ctx)
    }

    return nil
}
  • Related