fixed resources leaking
--HG-- branch : dev
This commit is contained in:
		
							parent
							
								
									adf3729627
								
							
						
					
					
						commit
						fe5a31a51e
					
				@ -32,7 +32,7 @@ Install both:
 | 
			
		||||
        log.Println(e)
 | 
			
		||||
    }
 | 
			
		||||
    w.AddServer("127.0.0.1:4730")
 | 
			
		||||
    w.AddFunc("ToUpper", ToUpper, 0)
 | 
			
		||||
    w.AddFunc("ToUpper", ToUpper, worker.Immediately)
 | 
			
		||||
    w.AddFunc("ToUpperTimeOut5", ToUpper, 5)
 | 
			
		||||
    w.Work()
 | 
			
		||||
 | 
			
		||||
@ -63,6 +63,7 @@ Xing Xing <mikespook@gmail.com>
 | 
			
		||||
 | 
			
		||||
# History
 | 
			
		||||
 | 
			
		||||
 * 0.1.2    Fixed issues: timeout executing, resources leaking.
 | 
			
		||||
 * 0.1.1    Fixed the issue of grabbing jobs.
 | 
			
		||||
 * 0.1      Code refactoring; Redesign the API.
 | 
			
		||||
 * 0.0.1    Initial implementation, ugly code-style, slow profermance and unstable API.
 | 
			
		||||
 | 
			
		||||
@ -12,15 +12,25 @@ def check_request_status(job_request):
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    client = gearman.GearmanClient(['localhost:4730', 'otherhost:4730'])
 | 
			
		||||
    try:
 | 
			
		||||
        completed_job_request = client.submit_job("ToUpper", "arbitrary binary data")
 | 
			
		||||
        check_request_status(completed_job_request)
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        print type(e)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        completed_job_request = client.submit_job("ToUpperTimeOut5", "arbitrary binary data")
 | 
			
		||||
        check_request_status(completed_job_request)
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        print type(e)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        completed_job_request = client.submit_job("ToUpperTimeOut20", "arbitrary binary data")
 | 
			
		||||
        check_request_status(completed_job_request)
 | 
			
		||||
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        print type(e)
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,7 @@ func main() {
 | 
			
		||||
        return nil
 | 
			
		||||
    }
 | 
			
		||||
    w.AddServer("127.0.0.1:4730")
 | 
			
		||||
    w.AddFunc("ToUpper", ToUpper, 0)
 | 
			
		||||
    w.AddFunc("ToUpper", ToUpper, worker.Immediately)
 | 
			
		||||
    w.AddFunc("ToUpperTimeOut5", ToUpperDelay10, 5)
 | 
			
		||||
    w.AddFunc("ToUpperTimeOut20", ToUpperDelay10, 20)
 | 
			
		||||
    go w.Work()
 | 
			
		||||
 | 
			
		||||
@ -91,12 +91,18 @@ func (job *Job) UpdateStatus(numerator, denominator int) {
 | 
			
		||||
    job.agent.WriteJob(newJob(common.REQ, common.WORK_STATUS, result))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// close the job
 | 
			
		||||
func (job *Job) Close() {
 | 
			
		||||
    close(job.c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// cancel the job executing
 | 
			
		||||
func (job *Job) cancel() {
 | 
			
		||||
    defer func() {recover()}()
 | 
			
		||||
    job.c <- true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// When a job was canceled, return a true form a channel
 | 
			
		||||
func (job *Job) Canceled() chan bool {
 | 
			
		||||
func (job *Job) Canceled() <-chan bool {
 | 
			
		||||
    return job.c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,8 @@ import (
 | 
			
		||||
const (
 | 
			
		||||
    Unlimited = 0
 | 
			
		||||
    OneByOne = 1
 | 
			
		||||
 | 
			
		||||
    Immediately = 0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
@ -21,7 +23,7 @@ var (
 | 
			
		||||
// Job handler
 | 
			
		||||
type JobHandler func(*Job) error
 | 
			
		||||
 | 
			
		||||
type JobFunc func(job *Job) ([]byte, error)
 | 
			
		||||
type JobFunc func(*Job) ([]byte, error)
 | 
			
		||||
 | 
			
		||||
// The definition of the callback function.
 | 
			
		||||
type jobFunc struct {
 | 
			
		||||
@ -179,21 +181,20 @@ func (worker *Worker) Work() {
 | 
			
		||||
    var job *Job
 | 
			
		||||
    for ok {
 | 
			
		||||
        if job, ok = <-worker.in; ok {
 | 
			
		||||
            go func() {
 | 
			
		||||
                defer job.Close()
 | 
			
		||||
                switch job.DataType {
 | 
			
		||||
                case common.ERROR:
 | 
			
		||||
                go func() {
 | 
			
		||||
                    _, err := common.GetError(job.Data)
 | 
			
		||||
                    worker.err(err)
 | 
			
		||||
                }()
 | 
			
		||||
                case common.JOB_ASSIGN, common.JOB_ASSIGN_UNIQ:
 | 
			
		||||
                go func() {
 | 
			
		||||
                    if err := worker.exec(job); err != nil {
 | 
			
		||||
                        worker.err(err)
 | 
			
		||||
                    }
 | 
			
		||||
                }()
 | 
			
		||||
                default:
 | 
			
		||||
                go worker.handleJob(job)
 | 
			
		||||
                    worker.handleJob(job)
 | 
			
		||||
                }
 | 
			
		||||
            }()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -272,26 +273,12 @@ func (worker *Worker) exec(job *Job) (err error) {
 | 
			
		||||
    if !ok {
 | 
			
		||||
        return common.Errorf("The function does not exist: %s", funcname)
 | 
			
		||||
    }
 | 
			
		||||
    var r result
 | 
			
		||||
    var r *result
 | 
			
		||||
    if f.timeout == 0 {
 | 
			
		||||
        r.data, r.err = f.f(job)
 | 
			
		||||
        d, e := f.f(job)
 | 
			
		||||
        r = &result{data:d, err: e}
 | 
			
		||||
    } else {
 | 
			
		||||
        rslt := make(chan *result)
 | 
			
		||||
        defer close(rslt)
 | 
			
		||||
        go func() {
 | 
			
		||||
            defer func() {recover()}()
 | 
			
		||||
            var r result
 | 
			
		||||
            r.data, r.err = f.f(job)
 | 
			
		||||
            rslt <- &r
 | 
			
		||||
        }()
 | 
			
		||||
        select {
 | 
			
		||||
        case re := <-rslt:
 | 
			
		||||
            r.data = re.data
 | 
			
		||||
            r.err = re.err
 | 
			
		||||
        case <-time.After(time.Duration(f.timeout) * time.Second):
 | 
			
		||||
            r.err = common.ErrExecTimeOut
 | 
			
		||||
            job.cancel()
 | 
			
		||||
        }
 | 
			
		||||
        r = execTimeout(f.f, job, time.Duration(f.timeout) * time.Second)
 | 
			
		||||
    }
 | 
			
		||||
    var datatype uint32
 | 
			
		||||
    if r.err == nil {
 | 
			
		||||
@ -327,3 +314,20 @@ type result struct {
 | 
			
		||||
    data []byte
 | 
			
		||||
    err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func execTimeout(f JobFunc, job *Job, timeout time.Duration) (r *result) {
 | 
			
		||||
    rslt := make(chan *result)
 | 
			
		||||
    defer close(rslt)
 | 
			
		||||
    go func() {
 | 
			
		||||
        defer func() {recover()}()
 | 
			
		||||
        d, e := f(job)
 | 
			
		||||
        rslt <- &result{data: d, err: e}
 | 
			
		||||
    }()
 | 
			
		||||
    select {
 | 
			
		||||
    case r = <-rslt:
 | 
			
		||||
    case <-time.After(timeout):
 | 
			
		||||
        go job.cancel()
 | 
			
		||||
        return &result{err:common.ErrExecTimeOut}
 | 
			
		||||
    }
 | 
			
		||||
    return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user