Comments (9)
Now that I ended up writing all of this I'm pumped to implement it. If you want to implement it go ahead or let me know so I can take it.
from fireorm.
@wovalle Happy for you to take it! I think you have a better idea of how it would work.
The only thing I'd mention with regards to your previous comment is I think it might be confusing having multiple ways of running transactions. IMO it should be just a single API to handle this, is there much value in having runTransaction
in bandRepository
too?
from fireorm.
Yeah, you're right. I cannot remove it now because that's a breaking change but I'll deprecate it and remove it in the upcoming v1.
from fireorm.
Makes sense 😄
from fireorm.
Yes, you're right. Today with fireorm you would need to open multiple transactions which is not only not ideal, it defeats the purpose of a transaction itself. A global runTransaction
makes a lot of sense.
How would the API look like? I want to enforce type checking in the transactions methods.
A runTransaction where you pass the type to all the methods in the TransactionRepository?
import { runTransaction } from 'fireorm';
runTransaction(async () => {
await transactionRepository.set<Entity>(entity);
})
cc @mamodom, I know you expressed interest in this feature before
from fireorm.
@wovalle That would work, although I believe it would lose type safety if the user forgot to add <Entity>
, which would allow bugs to occur.
Maybe something like this to enforce it better?
await transactionRepository.set(Entity, data);
Then the type could be something along the lines of this:
set(entity: T, data: keyof T)
from fireorm.
I took a look into this, I managed to get most of it done but I'm facing major hurdles when trying to separate the TransactionRepository
from AbstractFirestoreRepository
.
I switched over to the following syntax:
// Modified InstantiableIEntity
type Instantiable<T> = { new(): T }
findById(entity: Instantiable<T>, id: string): Promise<T> {
const { firestoreColRef } = getRepository(entity);
const query = firestoreColRef.doc(id);
return this.transaction.get(query).then(this.extractTFromDocSnap);
}
However, in the constructor for TransactionRepository
, there isn't a collection to pass to AbstractFirestoreRepository
. What would you suggest here? Transactions rely on some of the methods from the AbstractFirestoreRepository
, but overall it doesn't look like the two should be linked anymore.
from fireorm.
Originally I made TransactionRepository
inherit from AbstractFirestoreRepository
to avoid implementing the where*
methods again. It worked on that end but it ended up with the following downsides:
- Had to overwrite
limit
andorderBy*
methods and return errors - As you mentioned in another issue, update/create/delete methods are declared as async when they're just adding the operations to the transaction object, they should be sync
So I wouldn't be too against removing that relation if it inherits from BaseRepository
and implement the same interfaces IQueryBuilder
and IQueryExecutor
.
About your proposal in this comment I don't think that'll work the way I'm envisioning it. I have a requirement that you shouldn't need to pass T when you invoke a transaction from the repository
The way I see it is this something like this:
Having a generic Transaction
class with the normal transaction class that contains two methods: getRepository
and commit
. This Transaction
class will be the one that holds the private Firestore Transaction.
When invoked in a repository, the object passed to runTransaction will just be the result of getRepository(T>).
See the examples:
With Global runTransaction:
import { runTransaction } from 'fireorm';
runTransaction(transaction => {
const bandTransactionRepository = transaction.getRepository(Band);
const membersTransactionRepository = transaction.getRepository(Members);
const band = await bandTransactionRepository.findById('opeth');
const members = await membersTransactionRepository.whereEqualTo(m => b.bandId, 'opeth');
band.deleted = true;
members.forEach(m => {
m.bandDisabled = true;
membersTransactionRepository.update(m);
});
bandTransactionRepository.update(band);
await transaction.commit();
});
With runTransaction inside a repository:
import { getRepository } from 'fireorm';
const bandRepository = getRepository(Band);
bandRepository.runTransaction(bandTransactionRepository => {
// Where bandTransactionRepository is the same object returned by
// const bandTransactionRepository = transaction.getRepository(Band);
// in the example below
const band = await bandTransactionRepository.findById('opeth');
band.deleted = true;
bandTransactionRepository.update(band);
await bandTransactionRepository.commit();
})
from fireorm.
🎉 This issue has been resolved in version 0.13.0 🎉
The release is available on:
Your semantic-release bot 📦🚀
from fireorm.
Related Issues (20)
- Can't resolve 'class-validator' typescript HOT 1
- Support for BulkWriter HOT 2
- Getter methods decorated with @Ignore() are still saved HOT 2
- plainToClass is undefined HOT 2
- TypeError: classTransformer.plainToClass error when trying to find document from DB HOT 2
- Rename id in collection to _id HOT 2
- Feature Request: Support generic validation HOT 3
- The result of build has some nulls removed
- Error: Collection with name ClubPlayers has already been registered HOT 1
- how to parameterize the complex query options? HOT 1
- There is a way to auto query subcollections? HOT 2
- If we are inside a transaction, our subcollections should also be TransactionRepositories HOT 1
- Querying subcollection of subcollection seems to inject random doc number on its path HOT 1
- SubCollection does not create HOT 2
- Project Status HOT 2
- Querying missing fields HOT 3
- Add firestore timestamps to entities HOT 1
- Error: Firestore must be initialized first - on using customRepository HOT 2
- firebase-admin SDK Timestamps no longer compatible with fireorm collection-update method HOT 1
- Feature Request: Graceful Handling of Duplicate Collections/Subcollections for Fireorm v >=0.18.0 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fireorm.