#83 separate revision counter, add more docs (#83)

diff --git a/build/docker/server/Dockerfile b/build/docker/server/Dockerfile
index 03e1d98..0b3d122 100644
--- a/build/docker/server/Dockerfile
+++ b/build/docker/server/Dockerfile
@@ -15,7 +15,6 @@
 
 FROM ubuntu:19.04
 
-RUN apt-get update && apt-get install -y net-tools
 RUN mkdir -p /etc/servicecomb-kie/
 RUN mkdir -p /opt/servicecomb-kie/conf
 
diff --git a/deployments/db.js b/deployments/db.js
index 08cd781..288b2d9 100644
--- a/deployments/db.js
+++ b/deployments/db.js
@@ -28,7 +28,7 @@
     }
 );
 db.createCollection("counter");
-db.counter.insertOne( { name:"revision_counter",count: 1 } );
+db.counter.insertOne( { name:"revision_counter",count: 1,domain:"default" } );
 db.createCollection( "kv", {
     validator: { $jsonSchema: {
             bsonType: "object",
diff --git a/docs/configuration.rst b/docs/configuration.rst
index 1dea3e9..88fdf36 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -7,3 +7,4 @@
 
    configurations/storage
    configurations/registry
+   configurations/long_polling
diff --git a/docs/configurations/long_polling.md b/docs/configurations/long_polling.md
new file mode 100644
index 0000000..4dcd5fe
--- /dev/null
+++ b/docs/configurations/long_polling.md
@@ -0,0 +1,36 @@
+# Long polling
+*experimental*
+
+Kie leverage gossip protocol to broad cast cluster events. if client use query parameter "?wait=5s" to poll key value,
+this polling will become long polling and if there is key value change events, 
+server will response key values to client.
+
+kie must join to a cluster and listen to peer events
+
+start first node
+```shell script
+./kie --name=kie0 --listen-peer-addr=10.1.1.11:5000
+```
+
+start another node
+```shell script
+./kie --name=kie1 --listen-peer-addr=10.1.1.12:5000 --peer-addr=10.1.1.11:5000
+```
+
+### event payload and trigger condition
+
+condition: key value put or delete
+
+payload:
+```go
+{
+  "Key": "timeout",
+  "Action": "put",
+  "Labels": {
+    "app": "default",
+    "service": "order"
+  },
+  "DomainID": "default",
+  "Project": "default"
+}
+```
\ No newline at end of file
diff --git a/docs/configurations/registry.md b/docs/configurations/registry.md
index 7795515..da7ac0a 100644
--- a/docs/configurations/registry.md
+++ b/docs/configurations/registry.md
@@ -1,19 +1,18 @@
-# Registry
-kie server is able to register to a registry, so that other client is able to discover it registry service.
+# Use discovery service
+kie server is able to register to a discovery service, so that other client is able to discover it registry service.
 by default registry feature is disabled.
 ```yaml
 cse:
   service:
     registry:
       disabled: true
-...
 ```
 For example, kie is able to register to ServiceComb service center.
 
 
 ### Options
-the function is powered by go-chassis in chassis.yaml file 
-refer to https://docs.go-chassis.com/user-guides/registry.html
+this feature is powered by go-chassis,
+refer to https://docs.go-chassis.com/user-guides/registry.html to know how to use
 
 ### Example 
 Register to ServiceComb service center
diff --git a/docs/configurations/storage.md b/docs/configurations/storage.md
index dd5abc3..a221661 100644
--- a/docs/configurations/storage.md
+++ b/docs/configurations/storage.md
@@ -22,7 +22,7 @@
 db:
   uri: mongodb://kie:123@127.0.0.1:27017/kie
   poolSize: 10
-  timeout:  5m
+  timeout:  5s
   sslEnabled: true
   rootCAFile: /opt/kie/ca.crt
 ```
diff --git a/docs/development-guide/build.md b/docs/development-guide/build.md
index 2af29f6..8f825f4 100644
--- a/docs/development-guide/build.md
+++ b/docs/development-guide/build.md
@@ -1,40 +1,16 @@
-# Build
+# How to Build
 
-Download and run mongodb, 
-see [MongoDB Community Edition Installation Tutorials](https://docs.mongodb.com/manual/installation/#mongodb-community-edition-installation-tutorials)
-
-Write a script to create a user 
-```shell script
-cat <<EOM > native_db.js
-db.createUser(
-    {
-        user: "root",
-        pwd: "root",
-        roles:[
-            {
-                role: "readWrite",
-                db:   "kie"
-            }
-        ]
-    }
-);
-EOM
-```
-
-Exec native_db.js
-```shell script bash
-mongo 127.0.0.1/kie native_db.js
-```
+Download init and run mongodb as mentioned in get started section
 
 Build serivcecomb-kie binary
 
 ```shell script bash
-cd ${servicecomb_root_path}
+cd ${project_root_path}
 build/build_binary.sh
 ```
 
-This will build 4 packages for 4 different platforms in ${servicecomb_root_path}/release/kie directory.
-Choose the right one and unzip and run it.
+This will build 4 packages for different platforms in ${servicecomb_root_path}/release/kie directory.
+Choose the right one, unzip and run it.
 For Example:
 ```shell script bash
 cd ${servicecomb_root_path}/release/kie
diff --git a/docs/get-started.rst b/docs/get-started.rst
index 9da963e..7dbc3ec 100644
--- a/docs/get-started.rst
+++ b/docs/get-started.rst
@@ -6,3 +6,4 @@
    :glob:
 
    getstarted/install.md
+   getstarted/verify.md
diff --git a/docs/getstarted/install.md b/docs/getstarted/install.md
index ca611dd..82bcfac 100644
--- a/docs/getstarted/install.md
+++ b/docs/getstarted/install.md
@@ -3,23 +3,7 @@
 ### With docker
 Run mongodb server
 
-write a script to create a user 
-```shell script
-cat <<EOM > db.js
-db.createUser(
-    {
-        user: "root",
-        pwd: "root",
-        roles:[
-            {
-                role: "readWrite",
-                db:   "kie"
-            }
-        ]
-    }
-);
-EOM
-```
+use the [db init script](https://github.com/apache/servicecomb-kie/blob/master/deployments/db.js)
 
 ```shell script
 sudo docker run --name mongo -d \
@@ -27,8 +11,8 @@
     -e "MONGO_INITDB_ROOT_USERNAME=root" \
     -e "MONGO_INITDB_ROOT_PASSWORD=root" \
     -p 27017:27017 \
-    -v ${PWD}/db.js:/docker-entrypoint-initdb.d/db.js:ro \
-    mongo:3.4
+    -v ./deployments/db.js:/docker-entrypoint-initdb.d/db.js:ro \
+    mongo:4.0
 ```
 ```shell script
 export MONGO_IP=`sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' mongo`
@@ -43,32 +27,6 @@
     servicecomb/kie
 ```
 
-Put a key 
-```shell script
-curl -X PUT \
-  http://127.0.0.1:30110/v1/default/kie/kv/ingressRule.http \
-  -H 'Content-Type: application/json' \
-  -d '{
-	"value":"some rule",
-	"type": "yaml",
-	"labels":{"app":"default"}
-}'
-```
-
-response is 
-```json
-{
-    "_id": "5d6f27c5a1b287c5074e4538",
-    "label_id": "5d6f27c5a1b287c5074e4537",
-    "key": "ingressRule.http",
-    "value": "rule",
-    "value_type": "text",
-    "labels": {
-        "app": "default"
-    },
-    "revision": 1
-}
-```
 
 ### Run locally with Docker compose
 
@@ -88,27 +46,10 @@
 Download and run mongodb, 
 see [MongoDB Community Edition Installation Tutorials](https://docs.mongodb.com/manual/installation/#mongodb-community-edition-installation-tutorials)
 
-Write a script to create a user 
-```shell script
-cat <<EOM > native_db.js
-db.createUser(
-    {
-        user: "root",
-        pwd: "root",
-        roles:[
-            {
-                role: "readWrite",
-                db:   "kie"
-            }
-        ]
-    }
-);
-EOM
-```
 
-Exec native_db.js
+use the [db init script](https://github.com/apache/servicecomb-kie/blob/master/deployments/db.js)
 ```shell script bash
-mongo 127.0.0.1/kie native_db.js
+mongo 127.0.0.1/kie db.js
 ```
 
 Download the binary of kie, see https://apache.org/dyn/closer.cgi/servicecomb/servicecomb-kie/0.1.0/
diff --git a/docs/getstarted/verify.md b/docs/getstarted/verify.md
new file mode 100644
index 0000000..5b802d6
--- /dev/null
+++ b/docs/getstarted/verify.md
@@ -0,0 +1,30 @@
+# After running
+Put a key 
+```shell script
+curl -X PUT \
+  http://127.0.0.1:30110/v1/default/kie/kv/ingressRule \
+  -H 'Content-Type: application/json' \
+  -d '{
+	"value":"some rule",
+	"type": "yaml",
+	"labels":{"app":"default"}
+}'
+```
+
+response is 
+```json
+{
+ "id": "05529229-efc3-49ca-a765-05759b23ab28",
+ "label_id": "e7faac8e-053e-4906-99ab-989f61febe74",
+ "key": "ingressRule",
+ "value": "some rule",
+ "value_type": "text",
+ "create_revision": 13,
+ "update_revision": 13,
+ "labels": {
+  "app": "default"
+ }
+}
+```
+
+the api docs is http://127.0.0.1:30110/apidocs.json
\ No newline at end of file
diff --git a/docs/intro/concepts.md b/docs/intro/concepts.md
index 997cb1d..7f391fe 100644
--- a/docs/intro/concepts.md
+++ b/docs/intro/concepts.md
@@ -1,27 +1,46 @@
 # Concepts
 
-### Labels
-key value must belong to a identical label,
+### labels
+key value must belong to an identical label,
 a labels is equivalent to a map, it is represent as a json object
 ```json
 {
 "app": "some_app",
-"service": "payment",
+"service": "web",
 "environment": "production",
 "version": "1.0.1"
 }
 ```
+for each unique label map, kie will generate a label id for it and produce a db record.
 ### key value
-A key is usually related to some function in your program, let's say a new web UI should enable or not.
-the labels is just like a map to tell you where this program located in. the map says, 
-it is located in production environment,the version is 1.0.1
+A key value is usually a snippet configuration for your component, let's say a web UI widget should be enabled or not.
+But usually, a component has different version and deployed in different environments.
+the labels is indicates where this component located in. 
+below the labels indicates it is located in production environment,the version is 1.0.1
 ```json
 {
-	"value":"true",
-	"labels":{
-              "service": "web-console",
-              "environment": "production",
-              "version": "1.0.1"
-             }
+ "id": "05529229-efc3-49ca-a765-05759b23ab28",
+ "label_id": "e7faac8e-053e-4906-99ab-989f61febe74",
+ "key": "enable_a_function",
+ "value": "true",
+ "value_type": "text",
+ "create_revision": 13,
+ "update_revision": 13,
+ "labels": {
+     "app": "some_app",
+     "service": "web",
+     "environment": "production",
+     "version": "1.0.1"
+  }
 }
-```
\ No newline at end of file
+```
+
+### revision
+kie holds a global revision number it starts from 1, 
+each creation or update action of key value record will cause the increasing of this revision number,
+key value has a immutable attribute "create_revision" when first created.
+after each modify,  "update_revision" will increase.
+kie leverage this revision to reduce network cost, 
+when client polling for key values, it can give a revision number "?revision=200" in query parameter, 
+server side compare current revision with it , if they are the same, server will only return http status 304 to client.
+at each query server will return current revision to client with response header "X-Kie-Revision"
diff --git a/go.mod b/go.mod
index f65f24f..70eda61 100644
--- a/go.mod
+++ b/go.mod
@@ -11,8 +11,6 @@
 	github.com/golang/snappy v0.0.1 // indirect
 	github.com/hashicorp/mdns v1.0.1 // indirect
 	github.com/hashicorp/serf v0.8.5
-	github.com/onsi/ginkgo v1.10.1
-	github.com/onsi/gomega v1.7.0
 	github.com/satori/go.uuid v1.2.0
 	github.com/stretchr/testify v1.4.0
 	github.com/urfave/cli v1.20.0
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index 8a329f0..310b4e3 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -146,12 +146,12 @@
 	}
 	return labels, nil
 }
-func isRevised(ctx context.Context, revStr string) (bool, error) {
+func isRevised(ctx context.Context, revStr, domain string) (bool, error) {
 	rev, err := strconv.ParseInt(revStr, 10, 64)
 	if err != nil {
 		return false, ErrInvalidRev
 	}
-	latest, err := service.RevisionService.GetRevision(ctx)
+	latest, err := service.RevisionService.GetRevision(ctx, domain)
 	if err != nil {
 		return false, err
 	}
@@ -232,7 +232,7 @@
 		WriteErrResponse(rctx, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
 		return
 	}
-	rev, err := service.RevisionService.GetRevision(rctx.Ctx)
+	rev, err := service.RevisionService.GetRevision(rctx.Ctx, domain.(string))
 	if err != nil {
 		WriteErrResponse(rctx, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
 		return
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index 784c408..8851f5e 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -152,7 +152,7 @@
 		}
 		rctx.WriteHeader(http.StatusNotModified)
 	} else {
-		revised, err := isRevised(rctx.Ctx, revStr)
+		revised, err := isRevised(rctx.Ctx, revStr, domain.(string))
 		if err != nil {
 			if err == ErrInvalidRev {
 				WriteErrResponse(rctx, http.StatusBadRequest, err.Error(), common.ContentTypeText)
diff --git a/server/service/mongo/counter/revision.go b/server/service/mongo/counter/revision.go
index cb4a6a1..a90a8f1 100644
--- a/server/service/mongo/counter/revision.go
+++ b/server/service/mongo/counter/revision.go
@@ -33,9 +33,9 @@
 }
 
 //GetRevision return current revision number
-func (s *Service) GetRevision(ctx context.Context) (int64, error) {
+func (s *Service) GetRevision(ctx context.Context, domain string) (int64, error) {
 	collection := session.GetDB().Collection(session.CollectionCounter)
-	filter := bson.M{"name": revision}
+	filter := bson.M{"name": revision, "domain": domain}
 	cur, err := collection.Find(ctx, filter)
 	if err != nil {
 		if err.Error() == context.DeadlineExceeded.Error() {
@@ -56,9 +56,9 @@
 }
 
 //ApplyRevision increase revision number and return modified value
-func ApplyRevision(ctx context.Context) (int64, error) {
+func ApplyRevision(ctx context.Context, domain string) (int64, error) {
 	collection := session.GetDB().Collection(session.CollectionCounter)
-	filter := bson.M{"name": revision}
+	filter := bson.M{"name": revision, "domain": domain}
 	sr := collection.FindOneAndUpdate(ctx, filter,
 		bson.D{
 			{"$inc", bson.D{
diff --git a/server/service/mongo/counter/revision_test.go b/server/service/mongo/counter/revision_test.go
index d298942..4956251 100644
--- a/server/service/mongo/counter/revision_test.go
+++ b/server/service/mongo/counter/revision_test.go
@@ -32,9 +32,9 @@
 	err = session.Init()
 	assert.NoError(t, err)
 	s := &counter.Service{}
-	n, _ := s.GetRevision(context.TODO())
+	n, _ := s.GetRevision(context.TODO(), "default")
 	t.Log(n)
 
-	next, _ := counter.ApplyRevision(context.TODO())
+	next, _ := counter.ApplyRevision(context.TODO(), "default")
 	assert.Equal(t, n+1, next)
 }
diff --git a/server/service/mongo/kv/kv_dao.go b/server/service/mongo/kv/kv_dao.go
index 15e8eaa..87656de 100644
--- a/server/service/mongo/kv/kv_dao.go
+++ b/server/service/mongo/kv/kv_dao.go
@@ -39,7 +39,7 @@
 	collection := session.GetDB().Collection(session.CollectionKV)
 	var err error
 	kv.ID = uuid.NewV4().String()
-	revision, err := counter.ApplyRevision(ctx)
+	revision, err := counter.ApplyRevision(ctx, kv.Domain)
 	if err != nil {
 		openlogging.Error(err.Error())
 		return nil, err
@@ -69,7 +69,7 @@
 //updateKeyValue update key value and add new revision
 func updateKeyValue(ctx context.Context, kv *model.KVDoc) error {
 	var err error
-	kv.UpdateRevision, err = counter.ApplyRevision(ctx)
+	kv.UpdateRevision, err = counter.ApplyRevision(ctx, kv.Domain)
 	if err != nil {
 		return err
 	}
diff --git a/server/service/service.go b/server/service/service.go
index b3a82c7..67fb9e8 100644
--- a/server/service/service.go
+++ b/server/service/service.go
@@ -52,7 +52,7 @@
 	GetHistory(ctx context.Context, keyID string, options ...FindOption) ([]*model.KVDoc, error)
 }
 type Revision interface {
-	GetRevision(ctx context.Context) (int64, error)
+	GetRevision(ctx context.Context, domain string) (int64, error)
 }
 
 //Init init db session