Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .kokoro/functions/datastore.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,11 @@ env_vars: {
env_vars: {
key: "TRAMPOLINE_BUILD_FILE"
value: "github/nodejs-docs-samples/.kokoro/build.sh"
}
}


# Configure the docker image for kokoro-trampoline.
env_vars: {
key: "TRAMPOLINE_IMAGE"
value: "gcr.io/cloud-devrel-kokoro-resources/node:8-user"
}
103 changes: 50 additions & 53 deletions functions/datastore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ const {Datastore} = require('@google-cloud/datastore');
// Instantiates a client
const datastore = new Datastore();

const makeErrorObj = prop => {
return new Error(
`${prop} not provided. Make sure you have a "${prop.toLowerCase()}" property in your request`
);
};

/**
* Gets a Datastore key from the kind/key pair in the request.
*
Expand All @@ -28,21 +34,17 @@ const datastore = new Datastore();
* @param {string} requestData.kind Datastore kind.
* @returns {object} Datastore key object.
*/
function getKeyFromRequestData(requestData) {
const getKeyFromRequestData = requestData => {
if (!requestData.key) {
throw new Error(
'Key not provided. Make sure you have a "key" property in your request'
);
return Promise.reject(makeErrorObj('Key'));
}

if (!requestData.kind) {
throw new Error(
'Kind not provided. Make sure you have a "kind" property in your request'
);
return Promise.reject(makeErrorObj('Kind'));
}

return datastore.key([requestData.kind, requestData.key]);
}
};

/**
* Creates and/or updates a record.
Expand All @@ -57,28 +59,28 @@ function getKeyFromRequestData(requestData) {
* @param {object} req.body.value Value to save to Cloud Datastore, e.g. {"description":"Buy milk"}
* @param {object} res Cloud Function response context.
*/
exports.set = (req, res) => {
exports.set = async (req, res) => {
// The value contains a JSON document representing the entity we want to save
if (!req.body.value) {
throw new Error(
'Value not provided. Make sure you have a "value" property in your request'
);
const err = makeErrorObj('Value');
console.error(err);
res.status(500).send(err.message);
return;
}

const key = getKeyFromRequestData(req.body);
const entity = {
key: key,
data: req.body.value,
};
try {
const key = await getKeyFromRequestData(req.body);
const entity = {
key: key,
data: req.body.value,
};

return datastore
.save(entity)
.then(() => res.status(200).send(`Entity ${key.path.join('/')} saved.`))
.catch(err => {
console.error(err);
res.status(500).send(err.message);
return Promise.reject(err);
});
await datastore.save(entity);
res.status(200).send(`Entity ${key.path.join('/')} saved.`);
} catch (err) {
console.error(new Error(err.message)); // Add to Stackdriver Error Reporting
res.status(500).send(err.message);
}
};

/**
Expand All @@ -93,25 +95,22 @@ exports.set = (req, res) => {
* @param {string} req.body.key Key at which to retrieve the data, e.g. "sampletask1".
* @param {object} res Cloud Function response context.
*/
exports.get = (req, res) => {
const key = getKeyFromRequestData(req.body);
exports.get = async (req, res) => {
try {
const key = await getKeyFromRequestData(req.body);
const [entity] = await datastore.get(key);

return datastore
.get(key)
.then(([entity]) => {
// The get operation will not fail for a non-existent entity, it just
// returns an empty dictionary.
if (!entity) {
throw new Error(`No entity found for key ${key.path.join('/')}.`);
}
// The get operation returns an empty dictionary for non-existent entities
// We want to throw an error instead
if (!entity) {
throw new Error(`No entity found for key ${key.path.join('/')}.`);
}

res.status(200).send(entity);
})
.catch(err => {
console.error(err);
res.status(500).send(err.message);
return Promise.reject(err);
});
res.status(200).send(entity);
} catch (err) {
console.error(new Error(err.message)); // Add to Stackdriver Error Reporting
res.status(500).send(err.message);
}
};

/**
Expand All @@ -126,18 +125,16 @@ exports.get = (req, res) => {
* @param {string} req.body.key Key at which to delete data, e.g. "sampletask1".
* @param {object} res Cloud Function response context.
*/
exports.del = (req, res) => {
const key = getKeyFromRequestData(req.body);

exports.del = async (req, res) => {
// Deletes the entity
// The delete operation will not fail for a non-existent entity, it just
// doesn't delete anything
return datastore
.delete(key)
.then(() => res.status(200).send(`Entity ${key.path.join('/')} deleted.`))
.catch(err => {
console.error(err);
res.status(500).send(err);
return Promise.reject(err.message);
});
try {
const key = await getKeyFromRequestData(req.body);
await datastore.delete(key);
res.status(200).send(`Entity ${key.path.join('/')} deleted.`);
} catch (err) {
console.error(new Error(err.message)); // Add to Stackdriver Error Reporting
res.status(500).send(err.message);
}
};
19 changes: 7 additions & 12 deletions functions/datastore/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,24 @@
"node": ">=8.0.0"
},
"scripts": {
"e2e-test": "export FUNCTIONS_CMD='gcloud functions' && sh test/updateFunctions.sh && BASE_URL=\"https://$GCF_REGION-$GCLOUD_PROJECT.cloudfunctions.net/\" mocha test/*.test.js --timeout=60000",
"system-test": "export FUNCTIONS_CMD='functions' && sh test/updateFunctions.sh && BASE_URL=\"http://localhost:8010/$GCLOUD_PROJECT/$GCF_REGION\" && mocha test/*.test.js --timeout=60000",
"test": "npm run system-test"
"test": "mocha test/*.test.js --timeout=5000"
},
"dependencies": {
"@google-cloud/datastore": "^3.1.2",
"@google-cloud/datastore": "^4.1.1",
"supertest": "^4.0.0"
},
"devDependencies": {
"@google-cloud/functions-emulator": "^1.0.0-beta.4",
"@google-cloud/nodejs-repo-tools": "^3.3.0",
"@google-cloud/functions-framework": "^1.1.1",
"child-process-promise": "^2.2.1",
"mocha": "^6.0.0",
"proxyquire": "^2.1.0",
"request": "^2.88.0",
"requestretry": "^4.0.0",
"sinon": "^7.2.7",
"uuid": "^3.3.2"
},
"cloud-repo-tools": {
"requiresKeyFile": true,
"requiresProjectId": true,
"requiredEnvVars": [
"BASE_URL",
"GCF_REGION",
"FUNCTIONS_CMD"
]
"requiresProjectId": true
}
}
Loading