forked from yuxh/gearman-go
		
	pooling finished
This commit is contained in:
		
							parent
							
								
									af05460727
								
							
						
					
					
						commit
						962846c2f7
					
				@ -7,6 +7,7 @@ package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
    "sync"
 | 
			
		||||
    "errors"
 | 
			
		||||
    "math/rand"
 | 
			
		||||
    "github.com/mikespook/gearman-go/common"
 | 
			
		||||
)
 | 
			
		||||
@ -15,6 +16,10 @@ const (
 | 
			
		||||
    PoolSize = 10
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
    ErrNotFound = errors.New("Server Not Found")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type poolClient struct {
 | 
			
		||||
    *Client
 | 
			
		||||
    Rate int
 | 
			
		||||
@ -52,7 +57,10 @@ last string) (addr string) {
 | 
			
		||||
type Pool struct {
 | 
			
		||||
    SelectionHandler SelectionHandler
 | 
			
		||||
    ErrHandler common.ErrorHandler
 | 
			
		||||
 | 
			
		||||
    clients map[string]*poolClient
 | 
			
		||||
    last string
 | 
			
		||||
 | 
			
		||||
    mutex sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -90,25 +98,45 @@ func (pool *Pool) Remove(addr string) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pool *Pool) Do(funcname string, data []byte,
 | 
			
		||||
flag byte, h JobHandler) (handle string, err error) {
 | 
			
		||||
flag byte, h JobHandler) (addr, handle string) {
 | 
			
		||||
    client := pool.selectServer()
 | 
			
		||||
    handle = client.Do(funcname, data, flag, h)
 | 
			
		||||
    addr = client.addr
 | 
			
		||||
    return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pool *Pool) DoBg(funcname string, data []byte,
 | 
			
		||||
flag byte) (handle string, err error) {
 | 
			
		||||
flag byte) (addr, handle string) {
 | 
			
		||||
    client := pool.selectServer()
 | 
			
		||||
    handle = client.DoBg(funcname, data, flag)
 | 
			
		||||
    addr = client.addr
 | 
			
		||||
    return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Get job status from job server.
 | 
			
		||||
// !!!Not fully tested.!!!
 | 
			
		||||
func (pool *Pool) Status(handle string) (status *Status) {
 | 
			
		||||
func (pool *Pool) Status(addr, handle string) (status *Status, err error) {
 | 
			
		||||
    if client, ok := pool.clients[addr]; ok {
 | 
			
		||||
        status = client.Status(handle)
 | 
			
		||||
    } else {
 | 
			
		||||
        err = ErrNotFound
 | 
			
		||||
    }
 | 
			
		||||
    return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Send a something out, get the samething back.
 | 
			
		||||
func (pool *Pool) Echo(data []byte) (r []byte) {
 | 
			
		||||
func (pool *Pool) Echo(addr string, data []byte) (r []byte, err error) {
 | 
			
		||||
    var client *poolClient
 | 
			
		||||
    if addr == "" {
 | 
			
		||||
        client = pool.selectServer()
 | 
			
		||||
    } else {
 | 
			
		||||
        var ok bool
 | 
			
		||||
        if client, ok = pool.clients[addr]; !ok {
 | 
			
		||||
            err = ErrNotFound
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    r = client.Echo(data)
 | 
			
		||||
    return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -120,3 +148,15 @@ func (pool *Pool) Close() (err map[string]error) {
 | 
			
		||||
    }
 | 
			
		||||
    return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pool *Pool) selectServer() (client *poolClient) {
 | 
			
		||||
    for client == nil {
 | 
			
		||||
        addr := pool.SelectionHandler(pool.clients, pool.last)
 | 
			
		||||
        var ok bool
 | 
			
		||||
        if client, ok = pool.clients[addr]; ok {
 | 
			
		||||
            pool.last = addr
 | 
			
		||||
            break
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,30 +20,84 @@ func TestPoolAdd(t *testing.T) {
 | 
			
		||||
        t.Errorf("2 servers expected, %d got.", len(pool.clients))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
func TestPoolEcho(t *testing.T) {
 | 
			
		||||
    pool.JobHandler = func(job *Job) error {
 | 
			
		||||
        echo := string(job.Data)
 | 
			
		||||
        if echo == "Hello world" {
 | 
			
		||||
            t.Log(echo)
 | 
			
		||||
        } else {
 | 
			
		||||
            t.Errorf("Invalid echo data: %s", job.Data)
 | 
			
		||||
        }
 | 
			
		||||
        return nil
 | 
			
		||||
    echo, err := pool.Echo("", []byte("Hello world"))
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        t.Error(err)
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
    if string(echo) != "Hello world" {
 | 
			
		||||
        t.Errorf("Invalid echo data: %s", echo)
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _, err = pool.Echo("not exists", []byte("Hello world"))
 | 
			
		||||
    if err != ErrNotFound {
 | 
			
		||||
        t.Errorf("ErrNotFound expected, got %s", err)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPoolDoBg(t *testing.T) {
 | 
			
		||||
    if addr, handle := pool.DoBg("ToUpper", []byte("abcdef"),
 | 
			
		||||
        JOB_LOW); handle == "" {
 | 
			
		||||
        t.Error("Handle is empty.")
 | 
			
		||||
    } else {
 | 
			
		||||
        t.Log(addr, handle)
 | 
			
		||||
    }
 | 
			
		||||
    pool.Echo([]byte("Hello world"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPoolDo(t *testing.T) {
 | 
			
		||||
    if addr, handle, err := pool.Do("ToUpper", []byte("abcdef"), JOB_LOW|JOB_BG); err != nil {
 | 
			
		||||
        t.Error(err)
 | 
			
		||||
    jobHandler := func(job *Job) {
 | 
			
		||||
        str := string(job.Data)
 | 
			
		||||
        if str == "ABCDEF" {
 | 
			
		||||
            t.Log(str)
 | 
			
		||||
        } else {
 | 
			
		||||
            t.Errorf("Invalid data: %s", job.Data)
 | 
			
		||||
        }
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
    if addr, handle := pool.Do("ToUpper", []byte("abcdef"),
 | 
			
		||||
        JOB_LOW, jobHandler); handle == "" {
 | 
			
		||||
        t.Error("Handle is empty.")
 | 
			
		||||
    } else {
 | 
			
		||||
        t.Log(handle)
 | 
			
		||||
        t.Log(addr, handle)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPoolStatus(t *testing.T) {
 | 
			
		||||
    s1, err := pool.Status("127.0.0.1:4730", "handle not exists")
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        t.Error(err)
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
    if s1.Known {
 | 
			
		||||
        t.Errorf("The job (%s) shouldn't be known.", s1.Handle)
 | 
			
		||||
    }
 | 
			
		||||
    if s1.Running {
 | 
			
		||||
        t.Errorf("The job (%s) shouldn't be running.", s1.Handle)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addr, handle := pool.Do("Delay5sec", []byte("abcdef"), JOB_LOW, nil);
 | 
			
		||||
    s2, err := pool.Status(addr, handle)
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        t.Error(err)
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if !s2.Known {
 | 
			
		||||
        t.Errorf("The job (%s) should be known.", s2.Handle)
 | 
			
		||||
    }
 | 
			
		||||
    if s2.Running {
 | 
			
		||||
        t.Errorf("The job (%s) shouldn't be running.", s2.Handle)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _, err = pool.Status("not exists", "not exists")
 | 
			
		||||
    if err != ErrNotFound {
 | 
			
		||||
        t.Error(err)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
func TestPoolClose(t *testing.T) {
 | 
			
		||||
    return
 | 
			
		||||
    if err := pool.Close(); err != nil {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user