...

Source file src/github.com/go-kivik/kivik/v4/x/fsdb/changes.go

Documentation: github.com/go-kivik/kivik/v4/x/fsdb

     1  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
     2  // use this file except in compliance with the License. You may obtain a copy of
     3  // the License at
     4  //
     5  //  http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     9  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    10  // License for the specific language governing permissions and limitations under
    11  // the License.
    12  
    13  // Changes feed support
    14  //
    15  // At present, this driver provides only rudimentary Changes feed support. It
    16  // supports only one-off changes feeds (no continuous support), and this is
    17  // implemented by scanning the database directory, and returning each document
    18  // and its most recent revision only.
    19  
    20  package fs
    21  
    22  import (
    23  	"context"
    24  	"io"
    25  	"os"
    26  	"strings"
    27  
    28  	"github.com/go-kivik/kivik/v4/driver"
    29  	"github.com/go-kivik/kivik/v4/x/fsdb/cdb/decode"
    30  )
    31  
    32  type changes struct {
    33  	db    *db
    34  	ctx   context.Context
    35  	infos []os.FileInfo
    36  }
    37  
    38  var _ driver.Changes = &changes{}
    39  
    40  func (c *changes) ETag() string    { return "" }
    41  func (c *changes) LastSeq() string { return "" }
    42  func (c *changes) Pending() int64  { return 0 }
    43  
    44  func ignoreDocID(name string) bool {
    45  	if name[0] != '_' {
    46  		return false
    47  	}
    48  	if strings.HasPrefix(name, "_design/") {
    49  		return false
    50  	}
    51  	if strings.HasPrefix(name, "_local/") {
    52  		return false
    53  	}
    54  	return true
    55  }
    56  
    57  func (c *changes) Next(ch *driver.Change) error {
    58  	for {
    59  		if len(c.infos) == 0 {
    60  			return io.EOF
    61  		}
    62  		candidate := c.infos[len(c.infos)-1]
    63  		c.infos = c.infos[:len(c.infos)-1]
    64  		if candidate.IsDir() {
    65  			continue
    66  		}
    67  		for _, ext := range decode.Extensions() {
    68  			if strings.HasSuffix(candidate.Name(), "."+ext) {
    69  				base := strings.TrimSuffix(candidate.Name(), "."+ext)
    70  				docid, err := filename2id(base)
    71  				if err != nil {
    72  					// ignore unrecognized files
    73  					continue
    74  				}
    75  				if ignoreDocID(docid) {
    76  					continue
    77  				}
    78  				rev, deleted, err := c.db.metadata(candidate.Name(), ext)
    79  				if err != nil {
    80  					return err
    81  				}
    82  				if rev == "" {
    83  					rev = "1-"
    84  				}
    85  				ch.ID = docid
    86  				ch.Deleted = deleted
    87  				ch.Changes = []string{rev}
    88  				return nil
    89  			}
    90  		}
    91  	}
    92  }
    93  
    94  func (c *changes) Close() error {
    95  	return nil
    96  }
    97  
    98  func (d *db) Changes(ctx context.Context, _ driver.Options) (driver.Changes, error) {
    99  	f, err := os.Open(d.path())
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	dir, err := f.Readdir(-1)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	return &changes{
   108  		db:    d,
   109  		ctx:   ctx,
   110  		infos: dir,
   111  	}, nil
   112  }
   113  

View as plain text