Browse Source

fixed resources leaking

--HG--
branch : dev
tags/0.1.2
mikespook 11 years ago
parent
commit
fe5a31a51e
5 changed files with 59 additions and 38 deletions
  1. +2
    -1
      README.md
  2. +16
    -6
      example/py/client.py
  3. +1
    -1
      example/worker.go
  4. +7
    -1
      worker/job.go
  5. +33
    -29
      worker/worker.go

+ 2
- 1
README.md View File

@@ -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.


+ 16
- 6
example/py/client.py View File

@@ -12,16 +12,26 @@ def check_request_status(job_request):

def main():
client = gearman.GearmanClient(['localhost:4730', 'otherhost:4730'])
completed_job_request = client.submit_job("ToUpper", "arbitrary binary data")
check_request_status(completed_job_request)
try:
completed_job_request = client.submit_job("ToUpper", "arbitrary binary data")
check_request_status(completed_job_request)
except Exception as e:
print type(e)

completed_job_request = client.submit_job("ToUpperTimeOut5", "arbitrary binary data")
check_request_status(completed_job_request)

completed_job_request = client.submit_job("ToUpperTimeOut20", "arbitrary binary data")
check_request_status(completed_job_request)
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()


+ 1
- 1
example/worker.go View File

@@ -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()


+ 7
- 1
worker/job.go View File

@@ -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
}

+ 33
- 29
worker/worker.go View File

@@ -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 {
switch job.DataType {
case common.ERROR:
go func() {
go func() {
defer job.Close()
switch job.DataType {
case common.ERROR:
_, err := common.GetError(job.Data)
worker.err(err)
}()
case common.JOB_ASSIGN, common.JOB_ASSIGN_UNIQ:
go func() {
case common.JOB_ASSIGN, common.JOB_ASSIGN_UNIQ:
if err := worker.exec(job); err != nil {
worker.err(err)
}
}()
default:
go worker.handleJob(job)
}
default:
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…
Cancel
Save