-
Notifications
You must be signed in to change notification settings - Fork 108
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
Feature suggestion: transaction #59
Comments
"For what I'm building I need this feature" => Did you manage to have this feature? https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents/beginTransaction I see that on the Firebase Rest API document there are 2 methods above, which might help you somehow. If you did integrate those APIs, please create a PR |
Thanks @piavgh, actually seems that we need both methods to make the transaction work. The first one to create and the second to make it happens. I'm working without transaction for now. While I have few data it's ok. But as the database gets larger it can become a problem |
Duplicate of #65 |
This is not a duplicate, a batch write is not the same as transaction. |
Thanks, I must have missed the related text in batched write documentation:
|
Transactions are useful for atomic operations. In my case I need to update user creadits for the add-on. I've implemented this feature for my project. As this library's language is typesctipt, my code is not compatible. If someone wants to install transactions, here's how:
The code
this.transformDocument_ = FirestoreWrite.prototype.transformDocument_;
//
// original class code...
//
/**
* https://firebase.google.com/docs/firestore/reference/rest/v1beta1/Write#FieldTransform
*
* @typedef {Object} FieldTransform
* @property {String} fieldPath - path to field, use dots for nested fields: "parent.kid"
*
* // Union field transform_type can be only one of the following:
* @property {Number} [increment]
* @property {Number} [maximum]
* @property {Number} [minimum]
* @property {Array} [appendMissingElements] - for arrays
* @property {Array} [removeAllFromArray] - for arrays
*/
/**
* Transform document using transactions.
* https://firebase.google.com/docs/firestore/manage-data/transactions
*
* @param {String} path - path to the document in format: "collection/documentId"
* @param {Array<FieldTransform>} fieldTransforms
* @param {Request} request
*
*/
transformDocument(path, fieldTransforms) {
const baseUrl = this.baseUrl.slice(0, -1) + ':';
const request = new Request(baseUrl, this.authToken);
return this.transformDocument_(request, path, this.basePath, fieldTransforms);
} I've decided to add the code to "Write" class instead of creating a new class:
/**
* Transform document using transactions.
* https://firebase.google.com/docs/firestore/manage-data/transactions
*
* @param {Request} request
* @param {String} path
* * @param {Array<FieldTransform>} fieldTransforms
* @param {String} basePath
*
*/
transformDocument_(request, path, basePath, fieldTransforms) {
// API documents
// https://firebase.google.com/docs/firestore/reference/rest/v1beta1/projects.databases.documents/beginTransaction
// https://firebase.google.com/docs/firestore/reference/rest/v1beta1/projects.databases.documents/commit
const paypoadBeginTransaction = {
"options": {
"readWrite": {}
}
}
const transactionData = request.post('beginTransaction', paypoadBeginTransaction);
const transactionId = transactionData.transaction;
const write = {
"currentDocument": {
"exists": true // the target document must exist
},
"transform": {
"document": basePath + path,
fieldTransforms
},
}
const payloadCommit = {
"writes": [write],
"transaction": transactionId
}
const result = request.post('commit', payloadCommit);
return result;
} Usage: function test_transformDocument() {
/** @type FieldTransform */
var fieldTransform = {
fieldPath: 'credits.gpt5',
increment: {integer_value: -5}
}
var result = transformDocument_('test/max', [fieldTransform]);
console.log(JSON.stringify(result));
}
/**
* @param {String} path - path to the document in format: "collection/documentId"
* @param {Array<FieldTransform>} fieldTransforms
*/
function transformDocument_(path, fieldTransforms) {
/** @type Firestore */
var app = getFirestoreApp_('v1beta1');
return app.transformDocument(path, fieldTransforms)
}
/**
* @param {String} [apiVersion] - v1
*/
function getFirestoreApp_(apiVersion) {
var email = options.email; // PUT YOUR SERVICE ACCOUNT EMAIL HERE
var projectId = options.projectId; // PUT YOUR PROJECT ID HERE
var key = getFirestoreKey_(); // PUT YOUR KEY HERE
var app = getFirestore(email, key, projectId, apiVersion);
return app;
} As result, "credits" for my user were refuced by 5, it was 500, and not it is 495. Here's what I see in logs:
With this code I'm sure if 2 operations will try to change user credits at the same time, no collision will happen with my data. Usage notes
ConclusionI hope my solution will be helpful, and I hope one day a modified version of this code will be added to original library. Cheers to creator and maintaimers! |
I didn't find this feature on the project Readme, but I think it would be great to have it in the library as well. For what I'm building I need this feature
The text was updated successfully, but these errors were encountered: