func (p *FileTtlQ) Deq(uid interface{}) ([]byte, error) { retry := false for { select { case k := <-p.getQ(uid).Dequeue(): key, _ := k.(string) b, err := p.Ldb.Get([]byte(key), nil) if err != nil { return nil, err } if b != nil { v := &QValue{} json.Unmarshal(b, v) p.Ldb.Delete([]byte(key), nil) if v.Dod > utee.TickSec() || v.Dod == -1 { return v.Data, nil } } default: if retry { return nil, nil } time.Sleep(time.Duration(1) * time.Nanosecond) retry = true } } }
//todo 每个文件目录不能超过1000个文件,目录摆放需要规范 分成多级的 1000整除的目录,一个文件夹,不能超过1000 个文件 func main() { log.Println("hello") ttlQ := NewFTtlQ("/home/figo/data", "sampleTtlQ") st := utee.TickSec() for i := 0; i <= 100*10000; i++ { dvid := fmt.Sprintf("sysDevice%v", i) ttlQ.Enq(dvid, []byte(dvid), 60*60*24*7) if i%10000 == 0 && i > 0 { log.Println("10000 enq finish") } } log.Println("10 0000 device enqueue a message ,cost @t:", (utee.TickSec() - st)) log.Println("sleep 1.2 minute,then retry with gorutine") ttlQ.hibernateAll() time.Sleep(time.Second * time.Duration(70)) var wg sync.WaitGroup st = utee.TickSec() for i := 0; i <= 100*10000; i++ { dvid := fmt.Sprintf("sysDevice%v", i) wg.Add(1) exc := func() { defer wg.Done() ttlQ.Enq(dvid, []byte(dvid), 60*60*24*7) } go exc() } wg.Wait() log.Println("100 0000 device enqueue a message with gorutime,cost @t:", (utee.TickSec() - st)) ttlQ.hibernateAll() log.Println("shut down all queue") time.Sleep(time.Second * time.Duration(10)) for len(ttlQ.shut_q) > 0 { time.Sleep(time.Second * time.Duration(1)) } log.Println("all shut down done") }
//ttl unit is second func (p *FileTtlQ) Enq(uid interface{}, data []byte, ttl ...uint32) error { q := p.getQ(uid) k := string(uuid.NewUUID().String()) //16 byte q.Enqueue(k) t := int64(-1) //never ood (out of day) if len(ttl) > 0 { t = utee.TickSec() + int64(ttl[0]) } qv := QValue{ Data: data, Dod: t, } b, err := json.Marshal(qv) utee.Chk(err) p.Ldb.Put([]byte(k), b, nil) return nil }