Skip to content

Commit

Permalink
Merge branch 'release-0.14.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
albrow committed Dec 15, 2015
2 parents 2b2c4cc + 53520fd commit 986c05f
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 54 deletions.
19 changes: 18 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,21 @@ If you plan on submitting a pull request, you should:
2. Create a new "feature branch" off of **develop** (not master) with a descriptive name (e.g. fix-database-error).
3. Make your changes in the feature branch.
4. Run the tests to make sure that they still pass. Updated the tests if needed.
5. Submit a pull request to merge your feature branch into the **develop** branch. Please do not request to merge directly into master.
5. Submit a pull request to merge your feature branch into the **develop** branch. Please do not request to merge directly into master.

### Third-Party Dependencies

Zoom uses [Glide](https://github.com/Masterminds/glide) to manage dependencies.
If you update or add any new dependencies, make sure you edit glide.yaml
appropriately. All dependencies should be locked to a specific version in
glide.yaml.

1. If the project supports semantic versioning and the current version is
greater than or equal to 1.0, the version should be pinned to the current
major version. E.g., `version: 2.x`.
2. If the project supports semantic versioning and the current version is less
than 1.0, the version should be pinned to the latest patch. E.g.,
`version: 0.4.2`.
3. If the project does not support semantic versioning, then the version should
be pinned to the latest commit hash. E.g.,
`ref: 2b2c4ccb8692bb9d0ac6411c1fe47bb04be0ee05`.
90 changes: 49 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
Zoom
====

[![Version](https://img.shields.io/badge/version-0.13.1-5272B4.svg)](https://github.com/albrow/zoom/releases)
[![Version](https://img.shields.io/badge/version-0.14.0-5272B4.svg)](https://github.com/albrow/zoom/releases)
[![Circle CI](https://img.shields.io/circleci/project/albrow/zoom.svg)](https://circleci.com/gh/albrow/zoom)
[![GoDoc](https://godoc.org/github.com/albrow/zoom?status.svg)](https://godoc.org/github.com/albrow/zoom)

A blazing-fast datastore and querying engine for Go built on Redis.

Requires Redis version >= 2.8.9 and Go version >= 1.2. The latest version of both is recommended.
Requires Redis version >= 2.8.9 and Go version >= 1.5 with
`GO15VENDOREXPERIMENT=1`. The latest version of both is recommended.

Full documentation is available on
[godoc.org](http://godoc.org/github.com/albrow/zoom).
Expand Down Expand Up @@ -96,10 +97,18 @@ as Redis To Go, RedisLabs, Google Cloud Redis, or Amazon Elasticache.
If you need to install Redis, see the [installation instructions](http://redis.io/download) on the official
Redis website.

To install Zoom itself, run `go get github.com/albrow/zoom` to pull down the
To install Zoom itself, run `go get -u github.com/albrow/zoom` to pull down the
current master branch, or install with the dependency manager of your choice to
lock in a specific version.

Zoom supports the
[Go 1.5 vendor experiment](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo/edit)
and all dependencies are installed into the vendor folder, which is checked into
version control. To use Zoom, you must use Go version >= 1.5 and set
`GO15VENDOREXPERIMENT=1`. (Internally, Zoom uses
[Glide](https://github.com/Masterminds/glide) to manage dependencies,
but you do not need to install Glide to use Zoom).


Initialization
--------------
Expand Down Expand Up @@ -668,53 +677,52 @@ network, address, and database used.
You should see some runtimes for various operations. If you see an error or if the build fails, please
[open an issue](https://github.com/albrow/zoom/issues/new).

Here are the results from my laptop (2.3GHz quad-core i7, 8GB RAM) using a socket connection with Redis set
Here are the results from my laptop (2.8GHz quad-core i7 CPU, 16GB 1600MHz RAM) using a socket connection with Redis set
to append-only mode:

```
BenchmarkConnection 2000000 656 ns/op
BenchmarkPing 50000 26627 ns/op
BenchmarkSet 50000 36452 ns/op
BenchmarkGet 50000 27864 ns/op
BenchmarkSave 20000 58962 ns/op
BenchmarkSave100 2000 960483 ns/op
BenchmarkFind 30000 43054 ns/op
BenchmarkFind100 3000 562743 ns/op
BenchmarkFindAll100 2000 665035 ns/op
BenchmarkFindAll10000 20 68657190 ns/op
BenchmarkDelete 20000 61379 ns/op
BenchmarkDelete100 2000 1031886 ns/op
BenchmarkDeleteAll100 2000 968367 ns/op
BenchmarkDeleteAll1000 100 11857145 ns/op
BenchmarkCount100 50000 28340 ns/op
BenchmarkCount10000 50000 29746 ns/op
BenchmarkQueryFilterInt1From1 10000 149719 ns/op
BenchmarkQueryFilterInt1From10 10000 148245 ns/op
BenchmarkQueryFilterInt10From100 5000 264959 ns/op
BenchmarkQueryFilterInt100From1000 1000 1654756 ns/op
BenchmarkQueryFilterString1From1 10000 152185 ns/op
BenchmarkQueryFilterString1From10 10000 154507 ns/op
BenchmarkQueryFilterString10From100 5000 287958 ns/op
BenchmarkQueryFilterString100From1000 1000 1862549 ns/op
BenchmarkQueryFilterBool1From1 10000 146349 ns/op
BenchmarkQueryFilterBool1From10 10000 147950 ns/op
BenchmarkQueryFilterBool10From100 5000 276740 ns/op
BenchmarkQueryFilterBool100From1000 1000 1641239 ns/op
BenchmarkQueryOrderInt100 2000 681141 ns/op
BenchmarkQueryOrderInt10000 20 72602768 ns/op
BenchmarkQueryOrderString100 1000 1662290 ns/op
BenchmarkQueryOrderString10000 10 118660109 ns/op
BenchmarkQueryOrderBool100 2000 681808 ns/op
BenchmarkQueryOrderBool10000 20 71249344 ns/op
BenchmarkComplexQuery 10000 142476 ns/op
BenchmarkConnection-8 5000000 318 ns/op
BenchmarkPing-8 100000 15146 ns/op
BenchmarkSet-8 100000 18782 ns/op
BenchmarkGet-8 100000 15556 ns/op
BenchmarkSave-8 50000 29307 ns/op
BenchmarkSave100-8 3000 546427 ns/op
BenchmarkFind-8 50000 24767 ns/op
BenchmarkFind100-8 5000 374947 ns/op
BenchmarkFindAll100-8 5000 383919 ns/op
BenchmarkFindAll10000-8 30 47267433 ns/op
BenchmarkDelete-8 50000 29902 ns/op
BenchmarkDelete100-8 3000 530866 ns/op
BenchmarkDeleteAll100-8 2000 730934 ns/op
BenchmarkDeleteAll1000-8 200 9185093 ns/op
BenchmarkCount100-8 100000 16411 ns/op
BenchmarkCount10000-8 100000 16454 ns/op
BenchmarkQueryFilterInt1From1-8 20000 82152 ns/op
BenchmarkQueryFilterInt1From10-8 20000 83816 ns/op
BenchmarkQueryFilterInt10From100-8 10000 144206 ns/op
BenchmarkQueryFilterInt100From1000-8 2000 1010463 ns/op
BenchmarkQueryFilterString1From1-8 20000 87347 ns/op
BenchmarkQueryFilterString1From10-8 20000 88031 ns/op
BenchmarkQueryFilterString10From100-8 10000 158968 ns/op
BenchmarkQueryFilterString100From1000-8 2000 1088961 ns/op
BenchmarkQueryFilterBool1From1-8 20000 82537 ns/op
BenchmarkQueryFilterBool1From10-8 20000 84556 ns/op
BenchmarkQueryFilterBool10From100-8 10000 149463 ns/op
BenchmarkQueryFilterBool100From1000-8 2000 1017342 ns/op
BenchmarkQueryOrderInt100-8 3000 386156 ns/op
BenchmarkQueryOrderInt10000-8 30 50011375 ns/op
BenchmarkQueryOrderString100-8 2000 1004530 ns/op
BenchmarkQueryOrderString10000-8 20 77855970 ns/op
BenchmarkQueryOrderBool100-8 3000 387056 ns/op
BenchmarkQueryOrderBool10000-8 30 49116863 ns/op
BenchmarkComplexQuery-8 20000 84614 ns/op
```

The results of these benchmarks can vary widely from system to system, and so the benchmarks
here are really only useful for comparing across versions of Zoom, and for identifying possible
performance regressions or improvements during development. You should run your own benchmarks that
are closer to your use case to get a real sense of how Zoom will perform for you. High performance
is one of the top priorities for this project, because without that you are better off using an ORM
designed for SQL databases.
is one of the top priorities for this project.


Contributing
Expand Down
59 changes: 48 additions & 11 deletions collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

// File model_type.go contains code related to the Collection type.
// File collection.go contains code related to the Collection type.
// This includes all of the most basic operations like Save and Find.
// The Register method and associated methods are also included here.

Expand Down Expand Up @@ -52,13 +52,6 @@ type CollectionOptions struct {
Name string
}

// Name returns the name for the given collection. The name is a unique string
// identifier to use for the collection in redis. All models in this collection
// that are saved in the database will use the collection name as a prefix.
func (c *Collection) Name() string {
return c.spec.name
}

// NewCollection registers and returns a new collection of the given model type.
// You must create a collection for each model type you want to save. The type
// of model must be unique, i.e., not already registered, and must be a pointer
Expand Down Expand Up @@ -99,6 +92,13 @@ func (p *Pool) NewCollection(model Model, options *CollectionOptions) (*Collecti
}, nil
}

// Name returns the name for the given collection. The name is a unique string
// identifier to use for the collection in redis. All models in this collection
// that are saved in the database will use the collection name as a prefix.
func (c *Collection) Name() string {
return c.spec.name
}

// parseCollectionOptions returns a well-formed CollectionOptions struct. If
// passedOptions is nil, it uses all the default options. Else, for each zero
// value field in passedOptions, it uses the default value for that field.
Expand Down Expand Up @@ -155,6 +155,19 @@ func (c *Collection) FieldIndexKey(fieldName string) (string, error) {
return c.spec.fieldIndexKey(fieldName)
}

// newNilCollectionError returns an error with a message describing that
// methodName was called on a nil collection.
func newNilCollectionError(methodName string) error {
return fmt.Errorf("zoom: Called %s on nil collection. You must initialize the collection with Pool.NewCollection", methodName)
}

// newUnindexedCollectionError returns an error with a message describing that
// methodName was called on a collection that was not indexed. Certain methods
// can only be called on indexed collections.
func newUnindexedCollectionError(methodName string) error {
return fmt.Errorf("zoom: %s only works for indexed collections. To index the collection, set the Index property to true in CollectionOptions when calling Pool.NewCollection", methodName)
}

// Save writes a model (a struct which satisfies the Model interface) to the
// redis database. Save returns an error if the type of model does not match the
// registered Collection. To make a struct satisfy the Model interface, you can
Expand All @@ -177,6 +190,10 @@ func (c *Collection) Save(model Model) error {
// will be added to the transaction and returned as an error when the
// transaction is executed.
func (t *Transaction) Save(c *Collection, model Model) {
if c == nil {
t.setError(newNilCollectionError("Save"))
return
}
if err := c.checkModelType(model); err != nil {
t.setError(fmt.Errorf("zoom: Error in Save or Transaction.Save: %s", err.Error()))
return
Expand Down Expand Up @@ -370,6 +387,10 @@ func (c *Collection) Find(id string, model Model) error {
// will be added to the transaction and returned as an error when the transaction is
// executed.
func (t *Transaction) Find(c *Collection, id string, model Model) {
if c == nil {
t.setError(newNilCollectionError("Find"))
return
}
if err := c.checkModelType(model); err != nil {
t.setError(fmt.Errorf("zoom: Error in Find or Transaction.Find: %s", err.Error()))
return
Expand Down Expand Up @@ -458,8 +479,12 @@ func (c *Collection) FindAll(models interface{}) error {
// Any errors encountered will be added to the transaction and returned as an error
// when the transaction is executed.
func (t *Transaction) FindAll(c *Collection, models interface{}) {
if c == nil {
t.setError(newNilCollectionError("FindAll"))
return
}
if !c.index {
t.setError(fmt.Errorf("zoom: error in FindAll: FindAll only works for indexed collections. To index the collection, pass CollectionOptions to the NewCollection method."))
t.setError(newUnindexedCollectionError("FindAll"))
return
}
// Since this is somewhat type-unsafe, we need to verify that
Expand Down Expand Up @@ -490,8 +515,12 @@ func (c *Collection) Count() (int, error) {
// encountered will be added to the transaction and returned as an error when the
// transaction is executed.
func (t *Transaction) Count(c *Collection, count *int) {
if c == nil {
t.setError(newNilCollectionError("Count"))
return
}
if !c.index {
t.setError(fmt.Errorf("zoom: error in Count: Count only works for indexed collections. To index the collection, pass CollectionOptions to the NewCollection method."))
t.setError(newUnindexedCollectionError("Count"))
return
}
t.Command("SCARD", redis.Args{c.IndexKey()}, newScanIntHandler(count))
Expand Down Expand Up @@ -520,6 +549,10 @@ func (c *Collection) Delete(id string) (bool, error) {
// executed. You may pass in nil for deleted if you do not care whether or not
// the model was deleted.
func (t *Transaction) Delete(c *Collection, id string, deleted *bool) {
if c == nil {
t.setError(newNilCollectionError("Delete"))
return
}
// Delete any field indexes
// This must happen first, because it relies on reading the old field values
// from the hash for string indexes (if any)
Expand Down Expand Up @@ -581,8 +614,12 @@ func (c *Collection) DeleteAll() (int, error) {
// and returned as an error when the transaction is executed. You may pass in nil
// for count if you do not care about the number of models that were deleted.
func (t *Transaction) DeleteAll(c *Collection, count *int) {
if c == nil {
t.setError(newNilCollectionError("DeleteAll"))
return
}
if !c.index {
t.setError(fmt.Errorf("zoom: error in DeleteAll: DeleteAll only works for indexed collections. To index the collection, pass CollectionOptions to the NewCollection method."))
t.setError(newUnindexedCollectionError("DeleteAll"))
return
}
var handler ReplyHandler
Expand Down
2 changes: 1 addition & 1 deletion doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// atomic transactions, lua scripts, and running Redis commands
// directly if needed.
//
// Version 0.13.1
// Version 0.14.0
//
// For installation instructions, examples, and more information
// visit https://github.com/albrow/zoom.
Expand Down
12 changes: 12 additions & 0 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package: github.com/albrow/zoom
import:
- package: github.com/dchest/uniuri
ref: 53057c437f6ee51004d86e38f45be42273beff05
- package: github.com/garyburd/redigo
ref: 6ece6e0a09f28cc399b21550cbf37ab39ba63cce
subpackages:
- /redis
- package: github.com/tv42/base58
ref: b6649477bfe6276322b4eeaae8f5e947b49cec92

0 comments on commit 986c05f

Please sign in to comment.