Aaron Benton é um arquiteto experiente, especializado em soluções criativas para desenvolver aplicativos móveis inovadores. Ele tem mais de 10 anos de experiência em desenvolvimento de pilha completa, incluindo ColdFusion, SQL, NoSQL, JavaScript, HTML e CSS. Atualmente, Aaron é Arquiteto de Aplicativos da Shop.com em Greensboro, Carolina do Norte, e é um Campeão da comunidade do Couchbase.

Para nossa última postagem na seção Falsa vamos explorar como podemos aproveitar Falsa + Servidor Couchbase + Gateway de sincronização para colocar nosso ambiente local em funcionamento para o desenvolvimento móvel. Faremos isso usando Docker e docker-compose. Isenção de responsabilidade: não sou de forma alguma um especialista em Docker, este é apenas um exemplo do que fiz para configurar rapidamente um ambiente de desenvolvimento e um conjunto de dados.
Docker
Usaremos dois contêineres do Docker, um para Servidor Couchbase e um para Gateway de sincronização. Poderíamos definir um arquivo docker-compose.yaml que simplesmente extraísse do couchbase:latest e do couchbase/sync-gateway:latest, mas ainda haveria a necessidade de configuração manual e queremos poder automatizar o máximo possível para o nosso aplicativo. Para fazer isso, precisaremos criar nossos próprios contêineres a partir de ambos, adicionando nossos próprios scripts e configurações.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
./docker-compose.yaml version: '2' services: fakeit-couchbase: build: context: ./.docker/couchbase/ container_name: fakeit-couchbase ports: - "8091-8094:8091-8094" - "11210:11210" volumes: - ./:/app fakeit-syncgatway: build: context: ./.docker/sync-gateway/ container_name: fakeit-syncgateway depends_on: - fakeit-couchbase ports: - "4984-4985:4984-4985" volumes: - ./:/app |
Nosso arquivo docker-compose.yaml está primeiro criando um contêiner no Dockerfile a partir de ./.docker/couchbase/Dockerfile, que tem a seguinte aparência.
|
1 2 3 4 5 6 7 8 9 10 |
./.docker/couchbase/Dockerfile # start with couchbase FROM couchbase:latest # copy the configure script COPY scripts/configure-node.sh /opt/couchbase # execute the configure-node.sh script CMD ["/opt/couchbase/configure-node.sh"] |
Esse Dockerfile está realmente fazendo apenas duas coisas: copiando um script de configuração e executando esse script. O script configure-node.sh tem a seguinte aparência.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
./.docker/couchbase/scripts/configure-node.sh set -m /entrypoint.sh couchbase-server & echo 'Waiting 20 seconds for Couchbase service to start' sleep 20 # configure the cluster echo 'Configuring Cluster' /opt/couchbase/bin/couchbase-cli cluster-init -c localhost:8091 --cluster-username=Administrator --cluster-password=password --cluster-port=8091 --cluster-ramsize=500 --service=data # create the ecommerce bucket echo 'Creating ecommerce bucket' /opt/couchbase/bin/couchbase-cli bucket-create -c localhost:8091 -u Administrator -p password --bucket=ecommerce --bucket-eviction-policy=fullEviction --bucket-type=membase --bucket-priority=high --enable-index-replica=0 --bucket-port=11211 --enable-flush=1 --bucket-replica=1 --bucket-ramsize=200 echo 'Couchbase server is ready' fg 1 |
O script configure-node.sh está fazendo algumas coisas:
- Aguardando o início do serviço Couchbase para que ele possa ser configurado
- Inicialização da configuração do cluster
- Criação do nosso balde de comércio eletrônico
O contêiner do Couchbase já foi criado; o próximo contêiner que precisa ser criado é o contêiner do Sync Gateway. Por padrão, o contêiner do Sync Gateway usa o bucket do gateway de sincronização somente de memória da morsa. Precisaremos atualizar essa configuração fornecendo nosso próprio arquivo sync-gateway.json para que possamos atualizar as configurações de armazenamento e acesso. Por fim, o contêiner do Sync Gateway expõe apenas a porta 4984, que é a porta pública. Como isso é para fins de desenvolvimento, vamos expor a porta 4985, que é a porta do administrador.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
./.docker/sync-gateway/Dockerfile # Start with the base sync gateway FROM couchbase/sync-gateway:latest # Copy the sync-gateway.json into the container COPY sync-gateway.json /opt/sync_gateway/sync-gateway.json # Create Volume for data to persist RUN mkdir -p /opt/sync_gateway/data # Copy Entry Point COPY scripts/entrypoint.sh / ENTRYPOINT ["/entrypoint.sh"] # Copy the configure script COPY scripts/configure-node.sh /opt/sync_gateway # Configure the Sync Gateway and Start it CMD ["/opt/sync_gateway/configure-node.sh"] # port 4984: public port # port 4985: admin port EXPOSE 4984 4985 ./.docker/sync-gateway/sync-gateway.json { "interface": "0.0.0.0:4984", "adminInterface": "0.0.0.0:4985", "log": ["CRUD+", "REST+", "Changes+", "Attach+"], "CORS": { "Origin":[ "https://localhost:8000", "*" ], "LoginOrigin":[ "https://localhost:8000", "*" ], "Headers":["Content-Type"], "MaxAge": 1728000 }, "databases": { "ecommerce": { "server": "https://fakeit-couchbase:8091", "bucket": "ecommerce", "users": { "GUEST": { "disabled": false } }, "sync": "function(doc, oldDoc) { channel(doc.channels); }" } } } ./.docker/sync-gateway/scripts/configure-node.sh #!/bin/bash set -m echo 'Waiting 20 seconds for Couchbase service to start and warm up' sleep 20 echo 'Starting the Sync Gateway Service' /entrypoint.sh sync_gateway /opt/sync_gateway/sync-gateway.json echo 'Couchbase Sync Gateway is ready' |
Novamente, isso é apenas para fins de desenvolvimento. Você nunca deve permitir o acesso de qualquer lugar à sua adminInterface ou habilitar CONVIDADO acesso ao seu gateway de sincronização, a menos que haja um bom motivo para isso.
A estrutura do nosso aplicativo agora é a seguinte:

Agora que configuramos nossos contêineres do Docker e definimos nosso arquivo docker-compose.yaml, precisamos criar e iniciar os contêineres. Para isso, executamos o seguinte comando no diretório de aplicativos:
|
1 |
docker-compose up -d |
Observação: Para fins do screencast, o parâmetro -d para executar os contêineres no modo desanexado é omitido.

Modelos
Nossos contêineres já foram iniciados; a próxima coisa que precisamos fazer antes de gerar nosso conjunto de dados é atualizar os modelos para dar suporte ao atributo channels.
|
1 |
users.yaml |
Esse modelo só será sincronizado com canais específicos do usuário.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
name: Users type: object key: _id data: min: 1000 max: 2000 inputs: ./countries.json properties: _id: type: string description: The document id built by the prefix "user_" and the users id data: post_build: `user_${this.user_id}` channels: type: array data: post_build: | return [ `channel-user-${this.user_id}` ]; doc_type: type: string description: The document type data: value: "user" ... products.yaml |
Apenas por diversão, publicaremos esse modelo em um canal global no qual todos os nossos usuários estarão inscritos.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
name: Products type: object key: _id data: min: 500 max: 1000 inputs: - ./categories.csv pre_build: globals.current_category = faker.random.arrayElement(inputs.categories); properties: _id: type: string description: The document id data: post_build: `product_${this.product_id}` channels: type: array data: build: | return [ `channel-products` ]; doc_type: type: string description: The document type data: value: product ... orders.yaml |
Esse modelo só será sincronizado com canais específicos do usuário.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
name: Orders type: object key: _id data: dependencies: - products.yaml - users.yaml min: 5000 max: 6000 properties: _id: type: string description: The document id data: post_build: `order_${this.order_id}` channels: type: array data: build: | return [ `channel-user-${this.user_id}` ]; doc_type: type: string description: The document type data: value: "order" ... |
Agora que nossos modelos foram atualizados para oferecer suporte a canais, podemos gerar nosso conjunto de dados aleatórios e enviá-lo para Servidor Couchbase através do Gateway de sincronização API REST. Nós informamos Falsa para fazer isso usando o seguinte comando:
|
1 |
fakeit sync-gateway --server https://localhost:4984 --bucket ecommerce --verbose models/* |
Para fins de desenvolvimento, permitimos o acesso de convidados ao nosso Gateway de sincronização. No entanto, se o acesso de convidados estiver desativado, você ainda poderá usar Falsa especificando um nome de usuário e uma senha para um usuário existente usando o seguinte comando:
|
1 |
fakeit sync-gateway --server https://localhost:4984 --bucket ecommerce --username YOURUSERNAME --password YOURPASSWORD --verbose models/* |
Antes da saída do conjunto de dados gerado, Falsa será autenticado no Gateway de sincronização para recuperar as informações necessárias da sessão.

Testes
A próxima coisa que precisamos fazer é criar um usuário de gateway de sincronização para que possamos sincronizar seus documentos localmente. Para esse teste, vamos pegar um documento de usuário aleatório do nosso modelo Users e criar um usuário a partir desse documento. Neste exemplo, será user_1001, e criaremos o usuário usando o comando curl:
|
1 2 3 4 5 6 |
curl --silent --show-error \ -H "Content-Type: application/json; charset=UTF-8" \ -H "Content-type: application/json" \ -X PUT \ -d '{"name":"Domenic81","password":"pgid_Tubn0qoEtZ","admin_channels":["channel-user-1001", "channel-products"]}' \ 'https://localhost:4985/ecommerce/_user/Domenic81' |

Aplicativo
Criamos um pequeno VueJS projeto que utiliza PouchDB para se conectar ao Sync Gateway e extrair os documentos de um usuário autenticado. Nosso aplicativo mostrará apenas os diferentes tipos de documentos disponíveis, seus IDs e conteúdo.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
// register highlight.js vue component Vue.use(VueHighlightJS) // create local ecommerce database var db = new PouchDB('local_ecommerce', { auto_compaction: true, revs_limit: 3 }); // create remote ecommerce database var remote_db = new PouchDB('https://localhost:4984/ecommerce/', { auth: { username: 'Domenic81', password: 'pgid_Tubn0qoEtZ' }, skip_setup: true }); // merge remote database with local database PouchDB.sync(db, remote_db, { live: true, retry: true }) var app = new Vue({ el: '#app', data: { current_type: '', items: [], id: '', current: JSON.stringify({}), types: [], }, watch: { id(id) { if (id) { db.get(id).then((current) => this.current = JSON.stringify(current, null, 2)) } }, current_type(type) { this.id = '' // update the current item to be blank this.current = JSON.stringify({}) // when `current_type` changes update the items list with the current types list this.updateItems(type) .then(() => { if (!this.id) { this.id = this.items[0] } }) } }, methods: { updateItems(type) { return db.query('ecommerce/by_doc_type', { key: type, reduce: false }) .then((result) => { this.items = result.rows.map((item) => item.id) }) }, removeStyle(el) { setTimeout(() => { el.style = '' }, 1000) } }, created() { // create the view to be queried var ddoc = { _id: '_design/ecommerce', views: { by_doc_type: { map: function(doc) { if (doc.doc_type) { emit(doc.doc_type); } }.toString(), reduce: '_count' } } } db.put(ddoc) // design document created // call the design document view index immediately to trigger a build .then(() => db.query('ecommerce/by_doc_type', { limit: 0 })) .catch((err) => { // it is fine if this fails and returns a document conflict that just means it doesnt need to be created if (err.status !== 409) { throw err; } }) // get all of the doc types available .then(() => db.query('ecommerce/by_doc_type', { reduce: true, group: true })) .then((types) => { this.types = types.rows.map((type) => type.key) this.current_type = this.types[0] }) } }) |

O aplicativo de amostra completo pode ser visualizado em https://github.com/bentonam/fakeit-couchbase-mobile-example
Conclusão
Ao longo desta série, você viu como Falsa pode usar modelos YAML simples, gerar grandes quantidades de dados falsos e enviar esses dados para vários destinos diferentes. Confira o repositório, solicitações pull são bem-vindas, pois estamos sempre buscando melhorias e aprimoramentos para tornar a ferramenta mais útil para a comunidade. Também gostaria de aproveitar este momento para agradecer àqueles que fizeram contribuições para o projeto. A versão 1.0 não teria sido lançada sem a ajuda de Tyler Benton (@tjbenton21), também Trevor Brindle (@VinceKerrazzi), Jessica Kennedy (@mistersender), Adam Burdette (@RavenStorms619) e Brant Burnett (@btburnett3)
Anterior
- FakeIt Série 1 de 5: Geração de dados falsos
- FakeIt Série 2 de 5: Dados compartilhados e dependências
- Série FakeIt 3 de 5: Modelos Lean por meio de definições
- FakeIt Série 4 de 5: Trabalhando com dados existentes
