0

How can I create a disk-based delayed queue in Go?

I am writing a Go program to take certain actions on data after certain time intervals. Here is a stripped down version.

func IncomingJob (data MyStruct) {
    //Run immediately
    dosomething(&data, 1)
    time.Sleep(5 * time.Minute)
    //Run after 5 minutes has passed from initial arrival
    dosomething(&data, 2)
    time.Sleep(5 * time.Minute)
    //Run after 10 minutes has passed from initial arrival
    dosomething(&data, 3)
    time.Sleep(50 * time.Minute)
    //Run after 60 minutes has passed from initial arrival
    dosomething(&data, 4)
}

This func would be initialized as a goroutinue.

go IncomingJob(data)

The problem I am having is that each instance of IncomingJob runs for 60 minutes and the MyStruct object stays in memory for that duration. The total memory usage is pretty huge. If I want to support 1 million runs per hour, that means at any given time, there are 1 million MyStruct objects in memory waiting, doing nothing. I can use time.AfterFunc for this as well, but that doesn't change anything with respect to memory usage.

Is there some disk backed FIFO queue/buffer implementation in Go? That way I could have 3 queues (for different intervals) and poll it and sleep until its the correct time for the polled data to be reprocessed. This way I would lose some CPU cycles in serialization, add I/O latency to an otherwise in-memory application but save a massive amount of memory.

Update: time.AfterFunc uses a lot less memory.

func IncomingJob (data MyStruct) {
    //Run immediately
    dosomething(&data, 1)
    time.AfterFunc(5 * time.Minute, func() {
        //Run after 5 minutes has passed from initial arrival
        dosomething(&data, 2)
        time.AfterFunc(5 * time.Minute, func() {
            //Run after 10 minutes has passed from initial arrival
            dosomething(&data, 3)
        })
            time.AfterFunc(50 * time.Minute, func() {
                //Run after 50 minutes has passed from initial arrival
                dosomething(&data, 4)
        })
    })
}
Rick-777
  • 9,714
  • 5
  • 34
  • 50
sajal
  • 776
  • 1
  • 6
  • 23

1 Answers1

0

Sounds like a job for an embedded database. I'm sure a FIFO can be modelled pretty easily by eg. a NoSQL key/value store.

You might want to have a look at kv (author here). Catch: Values are limited to 64k, so you might need to compose separate FIFO items out of more than one K/V pair.

zzzz
  • 87,403
  • 16
  • 175
  • 139
  • http://godoc.org/github.com/cznic/kv#DB.First - How is first selected? Is it the earliest entered k,v which still exists in the DB? btw your kv looks perfect for another portion of the code should i need to add durability in the application. – sajal Aug 03 '13 at 15:30
  • @sajal: First: in the key collating order. So yes, if you use ordered number sequence (or time.Now().UnixNano()) as keys then .First will return the "oldest" item still in the DB. – zzzz Aug 03 '13 at 15:38