-
Notifications
You must be signed in to change notification settings - Fork 2k
[bigtable] - Add an example of a cloud function with Bigtable #1742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9cb1a30
5c87ab3
f4f1a50
0e260bc
fc3069b
4a3093c
d2c7277
d4f1e40
c560c4d
448a856
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| // Copyright 2020 Google LLC | ||
| // | ||
| // Licensed 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. | ||
|
|
||
| 'use strict'; | ||
|
|
||
| // [START bigtable_functions_quickstart] | ||
| // Imports the Google Cloud client library | ||
| const {Bigtable} = require('@google-cloud/bigtable'); | ||
|
|
||
| // Instantiates a client | ||
| const bigtable = new Bigtable(); | ||
|
|
||
| // Your Cloud Bigtable instance ID | ||
| const instanceId = 'your-instance'; | ||
|
|
||
| // Your Cloud Bigtable table ID | ||
| const tableId = 'mobile-time-series'; | ||
|
|
||
| /** | ||
| * HTTP Cloud Function. | ||
| * | ||
| * @param {Object} req Cloud Function request context. | ||
| * @param {Object} res Cloud Function response context. | ||
| */ | ||
| exports.get = async (req, res) => { | ||
| // Gets a reference to a Cloud Bigtable instance and database | ||
| const instance = bigtable.instance(instanceId); | ||
| const table = instance.table(tableId); | ||
|
|
||
| // Execute the query | ||
| try { | ||
| const prefix = 'phone#'; | ||
| let rows = []; | ||
| await table | ||
| .createReadStream({ | ||
| prefix, | ||
| }) | ||
| .on('error', err => { | ||
| res.send(`Error querying Bigtable: ${err}`); | ||
| res.status(500).end(); | ||
| }) | ||
| .on('data', row => { | ||
| rows.push( | ||
| `rowkey: ${row.id}, ` + | ||
| `os_build: ${row.data["stats_summary"]["os_build"][0].value}\n` | ||
| ) | ||
| }).on('end', () => { | ||
| rows.forEach(r => res.write(r)); | ||
| res.status(200).end(); | ||
| }); | ||
| } catch (err) { | ||
| res.send(`Error querying Bigtable: ${err}`); | ||
| res.status(500).end(); | ||
| } | ||
| }; | ||
| // [END bigtable_functions_quickstart] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| { | ||
| "name": "nodejs-docs-samples-functions-bigtable", | ||
| "version": "0.0.1", | ||
| "private": true, | ||
| "license": "Apache-2.0", | ||
| "author": "Google Inc.", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" | ||
| }, | ||
| "engines": { | ||
| "node": ">=8.0.0" | ||
| }, | ||
| "scripts": { | ||
| "test": "mocha test/*.test.js --timeout=20000", | ||
| "start": "functions-framework --target=get" | ||
| }, | ||
| "dependencies": { | ||
| "@google-cloud/bigtable": "^2.3.2", | ||
| "@google-cloud/functions-framework": "^1.5.1" | ||
| }, | ||
| "devDependencies": { | ||
| "mocha": "^7.0.0", | ||
| "proxyquire": "^2.1.0", | ||
| "sinon": "^9.0.0" | ||
| }, | ||
| "cloud-repo-tools": { | ||
| "requiresKeyFile": true, | ||
| "requiresProjectId": true | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| // Copyright 2020 Google LLC | ||
| // | ||
| // Licensed 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. | ||
|
|
||
| 'use strict'; | ||
|
|
||
| const proxyquire = require('proxyquire').noCallThru(); | ||
| const sinon = require('sinon'); | ||
| const assert = require('assert'); | ||
| const {PassThrough} = require('stream'); | ||
|
|
||
| let mockedStream; | ||
| const rows = [ | ||
| { | ||
| id: "phone#4c410523#20190501", | ||
| data: { | ||
| stats_summary: { | ||
| os_build: [{ | ||
| value: "PQ2A.190405.003" | ||
| }] | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| id: "phone#5c10102#20190501", | ||
| data: { | ||
| stats_summary: { | ||
| os_build: [{ | ||
| value: "PQ2A.190406.000" | ||
| }] | ||
| } | ||
| }, | ||
| }, | ||
| ]; | ||
|
|
||
| const query = { | ||
| prefix: "phone#" | ||
| }; | ||
|
|
||
| const getSample = () => { | ||
| mockedStream = require('stream').Readable.from(rows); | ||
|
|
||
| const tableMock = { | ||
| createReadStream: sinon.stub().returns(mockedStream), | ||
| }; | ||
| const instanceMock = { | ||
| table: sinon.stub().returns(tableMock), | ||
| }; | ||
| const bigtableMock = { | ||
| instance: sinon.stub().returns(instanceMock), | ||
| }; | ||
|
|
||
| const BigtableMock = sinon.stub().returns(bigtableMock); | ||
|
|
||
| return { | ||
| program: proxyquire('../', { | ||
| '@google-cloud/bigtable': {Bigtable: BigtableMock}, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it worth testing this directly instead of using a mocked client library?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have a strong opinion about this, I'm just following what every other sample has done. |
||
| }), | ||
| mocks: { | ||
| bigtable: bigtableMock, | ||
| table: tableMock, | ||
| instance: instanceMock, | ||
| res: { | ||
| status: sinon.stub().returnsThis(), | ||
| send: sinon.stub().returnsThis(), | ||
| end: sinon.stub().returnsThis(), | ||
| write: sinon.stub().returnsThis(), | ||
| }, | ||
| }, | ||
| }; | ||
| }; | ||
|
|
||
| describe('bigtable_functions_quickstart', () => { | ||
| it('get: Gets rows', async () => { | ||
| const sample = getSample(); | ||
| const {mocks} = sample; | ||
| await sample.program.get(mocks.req, mocks.res); | ||
| rows.forEach((row) => { | ||
| mockedStream.emit('data', row); | ||
| }); | ||
| mockedStream.emit("end"); | ||
| assert.strictEqual(mocks.bigtable.instance.called, true); | ||
| assert.strictEqual(mocks.instance.table.called, true); | ||
| assert.strictEqual(mocks.table.createReadStream.calledWith(query), true); | ||
| assert.strictEqual( | ||
| mocks.res.write.calledWith( | ||
| 'rowkey: phone#4c410523#20190501, os_build: PQ2A.190405.003\n' | ||
| ), | ||
| true | ||
| ); | ||
| assert.strictEqual( | ||
| mocks.res.write.calledWith( | ||
| 'rowkey: phone#5c10102#20190501, os_build: PQ2A.190406.000\n' | ||
| ), | ||
| true | ||
| ); | ||
| assert.strictEqual(mocks.res.end.called, true); | ||
| }); | ||
| }); | ||
Uh oh!
There was an error while loading. Please reload this page.