backend/helpers/pluginhelper/api/iterator.go (123 lines of code) (raw):

/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package api import ( "reflect" "time" "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" ) // Iterator FIXME ... type Iterator interface { HasNext() bool Fetch() (interface{}, errors.Error) Close() errors.Error } // DalCursorIterator FIXME ... type DalCursorIterator struct { db dal.Dal cursor dal.Rows elemType reflect.Type batchSize int } // NewDalCursorIterator FIXME ... func NewDalCursorIterator(db dal.Dal, cursor dal.Rows, elemType reflect.Type) (*DalCursorIterator, errors.Error) { return NewBatchedDalCursorIterator(db, cursor, elemType, -1) } // NewBatchedDalCursorIterator FIXME ... func NewBatchedDalCursorIterator(db dal.Dal, cursor dal.Rows, elemType reflect.Type, batchSize int) (*DalCursorIterator, errors.Error) { return &DalCursorIterator{ db: db, cursor: cursor, elemType: elemType, batchSize: batchSize, }, nil } // HasNext increments the row curser. If we're at the end, it'll return false. func (c *DalCursorIterator) HasNext() bool { return c.cursor.Next() } // Fetch if batching is disabled, it'll read a single row, otherwise it'll read as many rows up to the batch size, and the // runtime return type will be []interface{}. Note, HasNext needs to have been called before invoking this. func (c *DalCursorIterator) Fetch() (interface{}, errors.Error) { if c.batchSize > 0 { return c.batchedFetch() } if c.batchSize != -1 { panic("invalid batch size") } elem := reflect.New(c.elemType).Interface() err := c.db.Fetch(c.cursor, elem) if err != nil { return nil, err } return elem, nil } func (c *DalCursorIterator) batchedFetch() (interface{}, errors.Error) { var elems []interface{} for i := 1; ; i++ { elem := reflect.New(c.elemType).Interface() err := c.cursor.Scan(elem) if err != nil { return nil, errors.Convert(err) } elems = append(elems, elem) if i == c.batchSize || !c.HasNext() { break } } return elems, nil } // Close iterator func (c *DalCursorIterator) Close() errors.Error { return errors.Convert(c.cursor.Close()) } var _ Iterator = (*DalCursorIterator)(nil) // DateIterator FIXME ... type DateIterator struct { startTime time.Time endTime time.Time Days int Current int } // DatePair FIXME ... type DatePair struct { PairStartTime time.Time PairEndTime time.Time } // HasNext FIXME ... func (c *DateIterator) HasNext() bool { return c.Current < c.Days } // Fetch FIXME ... func (c *DateIterator) Fetch() (interface{}, errors.Error) { c.Current++ return &DatePair{ PairStartTime: c.startTime.AddDate(0, 0, c.Current), PairEndTime: c.endTime.AddDate(0, 0, c.Current), }, nil } // Close iterator func (c *DateIterator) Close() errors.Error { return nil } // NewDateIterator FIXME ... func NewDateIterator(days int) (*DateIterator, errors.Error) { endTime := time.Now().Truncate(24 * time.Hour) return &DateIterator{ startTime: endTime.AddDate(0, 0, -days-1), endTime: endTime.AddDate(0, 0, -days), Days: days, Current: 0, }, nil } // QueueIterator implements Iterator based on Queue type QueueIterator struct { queue *Queue } // HasNext increments the row curser. If we're at the end, it'll return false. func (q *QueueIterator) HasNext() bool { return q.queue.GetCount() > 0 } // Fetch current item func (q *QueueIterator) Fetch() (interface{}, errors.Error) { node := q.queue.Pull() if node == nil { return nil, nil } else { return node.Data(), nil } } // Push a data into queue func (q *QueueIterator) Push(data interface{}) { q.queue.Push(NewQueueIteratorNode(data)) } // Close releases resources func (q *QueueIterator) Close() errors.Error { q.queue.CleanWithOutLock() return nil } // NewQueueIterator creates a new QueueIterator func NewQueueIterator() *QueueIterator { return &QueueIterator{ queue: NewQueue(), } }