Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
447 views
in Technique[技术] by (71.8m points)

go - Watch for changes in a queue containing struct

I have two goroutines:

  1. first one adds task to queue
  2. second cleans up from the queue based on status

Add and cleanup might not be simultaneous.

If the status of task is success, I want to delete the task from the queue, if not, I will retry for status to be success (will have time limit). If that fails, I will log and delete from queue.

We can't communicate between add and delete because that is not how the real world scenario works.

I want something like a watcher which monitors addition in queue and does the following cleanup. To increase complexity, Add might be adding even during cleanup is happening (not shown here). I want to implement it without using external packages.

How can I achieve this?

type Task struct {
    name   string
    status string //completed, failed
}

var list []*Task

func main() {
    done := make(chan bool)
    go Add()
    time.Sleep(15)
    go clean(done)
    <-done
}

func Add() {
    t1 := &Task{"test1", "completed"}
    t2 := &Task{"test2", "failed"}
    list = append(list, t1, t2)
}

func clean() {
    for k, v := range list {
        if v.status == "completed" {
            RemoveIndex(list, k)
        } else {
            //for now consider this as retry
            v.status == "completed"
        }
        if len(list) > 0 {
            clean()
        }
        <-done
    }
}

func RemoveIndex(s []int, index int) []int {
    return append(s[:index], s[index+1:]...)
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

so i found a solution which works for me and posting it here for anyone it might be helpful for.

in my main i have added a ticker which runs every x seconds to watch if something is added in the queue.

type Task struct {
    name   string
    status string //completed, failed
}

var list []*Task

func main() {
    done := make(chan bool)
c := make(chan os.Signal, 2)
    go Add()
    go func() {
        for {
            select {
            // case <-done:
            //  Cleaner(k)
            case <-ticker.C:
                Monitor(done)
            }
        }
    }()
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    <-c
    //waiting for interrupt here

}

func Add() {
    t1 := &Task{"test1", "completed"}
    t2 := &Task{"test2", "failed"}
    list = append(list, t1, t2)
}

func Monitor(done chan bool) {
    if len(list) > 0 {
        Cleaner()
    }
}

func cleaner(){
  //do cleaning here
 // pop each element from queue and delete
}

func RemoveIndex(s []int, index int) []int {
    return append(s[:index], s[index+1:]...)
}

so now this solution does not need to depend on communication between go routines, in a real world scenario, the programme never dies and keeps adding and cleaning based on use case.you can optimize better by locking and unlocking before addition to queue and deletion from queue.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...