Skip to content
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

When the persistent database and business database of cap are not the same database, is there any good way to implement transactions? #970

Closed
dashiell-zhang opened this issue Aug 6, 2021 · 10 comments
Labels

Comments

@dashiell-zhang
Copy link

When the persistent database of cap is different from the business database, how should the transaction be handled? According to the following code, the publish information of cap will be inserted into the DB of the business database instead of the DB of cap itself

      using (var trans = db.Database.BeginTransaction(cap))
                {
                    var x = new TCount();
                    x.ClientSign = db.ClientSign;
                    x.Count = 1;
                    x.Id = Guid.NewGuid();
                    x.CreateTime = DateTime.Now;

                    db.TCount.Add(x);

                    db.SaveChanges();

                    cap.Publish("S", DateTime.Now);

                    trans.Commit();
                }

If you use environment transactions like the following code, you will directly generate bugs in the final commit phase

                using (TransactionScope ts = new TransactionScope())
                {

                    var x = new TCount();
                    x.ClientSign = db.ClientSign;
                    x.Count = 1;
                    x.Id = Guid.NewGuid();
                    x.CreateTime = DateTime.Now;

                    db.TCount.Add(x);

                    db.SaveChanges();

                    cap.Publish("S", DateTime.Now);

                    ts.Complete();
                }

When the persistent database and business database of cap are not the same database, is there any good way to implement transactions?

@xiangxiren
Copy link
Contributor

This is not a good way.
The realization principle of CAP is to rely on database transactions to ensure the success or failure of the business and the message at the same time. If you are not in the same database, you cannot use the same database transaction.

@dashiell-zhang
Copy link
Author

Can an API project inject multiple cap services, each of which is assigned a persistent library

@xiangxiren
Copy link
Contributor

Can an API project inject multiple cap services, each of which is assigned a persistent library

What is the significance of this?

@dashiell-zhang
Copy link
Author

Can an API project inject multiple cap services, each of which is assigned a persistent library

What is the significance of this?

I have a set of SaaS projects, in which the logic is a set of code, and then through the domain name information during access, I can judge the connection to different customer databases, such as a.com to db-a and c.com to db-c. this function has been realized.
When integrating cap, my original idea was that the cap service uses a public database, but now I encounter the restriction that the cap must be the same library as the customer's business. Therefore, I wonder whether I can traverse and start a cap service for all the customer's dB when the code is started.

@xiangxiren
Copy link
Contributor

Can an API project inject multiple cap services, each of which is assigned a persistent library

What is the significance of this?

I have a set of SaaS projects, in which the logic is a set of code, and then through the domain name information during access, I can judge the connection to different customer databases, such as a.com to db-a and c.com to db-c. this function has been realized.
When integrating cap, my original idea was that the cap service uses a public database, but now I encounter the restriction that the cap must be the same library as the customer's business. Therefore, I wonder whether I can traverse and start a cap service for all the customer's dB when the code is started.

CAP currently does not support dynamic database switching.

@dashiell-zhang
Copy link
Author

Can an API project inject multiple cap services, each of which is assigned a persistent library

What is the significance of this?

I have a set of SaaS projects, in which the logic is a set of code, and then through the domain name information during access, I can judge the connection to different customer databases, such as a.com to db-a and c.com to db-c. this function has been realized.
When integrating cap, my original idea was that the cap service uses a public database, but now I encounter the restriction that the cap must be the same library as the customer's business. Therefore, I wonder whether I can traverse and start a cap service for all the customer's dB when the code is started.

CAP currently does not support dynamic database switching.

            using (var scope = new TransactionScope())
            {
                using var db = new ClientDbContext();

                var x = new TCount();
                x.ClientSign = db.ClientSign;
                x.Count = 1;
                x.Id = Guid.NewGuid();
                x.CreateTime = DateTime.Now;

                db.TCount.Add(x);

                db.SaveChanges();

                cap.Publish("S", DateTime.Now);

                scope.Complete();
            }

I currently do this, and then enable the preprocessing transaction in the postgresql configuration, it seems that no bugs will be caused, and the effect is realized. When the final transaction is submitted, the operation transactions of cap and business db will be submitted uniformly, but this requires modification of postgresql. In the configuration file of max_prepared_transactions = 100, the default is 0 to indicate that it is disabled, but it is not clear to open the preprocessing transaction of the database, whether there is any unknown problem

@xiangxiren
Copy link
Contributor

Can an API project inject multiple cap services, each of which is assigned a persistent library

What is the significance of this?

I have a set of SaaS projects, in which the logic is a set of code, and then through the domain name information during access, I can judge the connection to different customer databases, such as a.com to db-a and c.com to db-c. this function has been realized.
When integrating cap, my original idea was that the cap service uses a public database, but now I encounter the restriction that the cap must be the same library as the customer's business. Therefore, I wonder whether I can traverse and start a cap service for all the customer's dB when the code is started.

CAP currently does not support dynamic database switching.

            using (var scope = new TransactionScope())
            {
                using var db = new ClientDbContext();

                var x = new TCount();
                x.ClientSign = db.ClientSign;
                x.Count = 1;
                x.Id = Guid.NewGuid();
                x.CreateTime = DateTime.Now;

                db.TCount.Add(x);

                db.SaveChanges();

                cap.Publish("S", DateTime.Now);

                scope.Complete();
            }

I currently do this, and then enable the preprocessing transaction in the postgresql configuration, it seems that no bugs will be caused, and the effect is realized. When the final transaction is submitted, the operation transactions of cap and business db will be submitted uniformly, but this requires modification of postgresql. In the configuration file of max_prepared_transactions = 100, the default is 0 to indicate that it is disabled, but it is not clear to open the preprocessing transaction of the database, whether there is any unknown problem

You only did a successful test. Have you ever done any one step exception and all operations can be rolled back normally?
The cap service uses a public database, which violates the principle of local message tables. Therefore, normality cannot be guaranteed.

@dashiell-zhang
Copy link
Author

Can an API project inject multiple cap services, each of which is assigned a persistent library

What is the significance of this?

I have a set of SaaS projects, in which the logic is a set of code, and then through the domain name information during access, I can judge the connection to different customer databases, such as a.com to db-a and c.com to db-c. this function has been realized.
When integrating cap, my original idea was that the cap service uses a public database, but now I encounter the restriction that the cap must be the same library as the customer's business. Therefore, I wonder whether I can traverse and start a cap service for all the customer's dB when the code is started.

CAP currently does not support dynamic database switching.

            using (var scope = new TransactionScope())
            {
                using var db = new ClientDbContext();

                var x = new TCount();
                x.ClientSign = db.ClientSign;
                x.Count = 1;
                x.Id = Guid.NewGuid();
                x.CreateTime = DateTime.Now;

                db.TCount.Add(x);

                db.SaveChanges();

                cap.Publish("S", DateTime.Now);

                scope.Complete();
            }

I currently do this, and then enable the preprocessing transaction in the postgresql configuration, it seems that no bugs will be caused, and the effect is realized. When the final transaction is submitted, the operation transactions of cap and business db will be submitted uniformly, but this requires modification of postgresql. In the configuration file of max_prepared_transactions = 100, the default is 0 to indicate that it is disabled, but it is not clear to open the preprocessing transaction of the database, whether there is any unknown problem

You only did a successful test. Have you ever done any one step exception and all operations can be rolled back normally?
The cap service uses a public database, which violates the principle of local message tables. Therefore, normality cannot be guaranteed.

https://www.highgo.ca/2020/01/28/understanding-prepared-transactions-and-handling-the-orphans/
This article describes some shortcomings. It seems that we still need to rebuild the architecture. It is indeed the most reliable to rely on the local message table, but the current project, a set of code serves multiple customers, how to service on a set of code. AddCap is a problem many times

@xiangxiren
Copy link
Contributor

Close this issue, regarding multi-tenant support, we will have a unified discussion into #699

@BraveJJJ
Copy link

API 项目是否可以注入多个 cap 服务,每个服务都分配有一个持久库

这有什么意义呢?

我有一套 SaaS 项目,其中的逻辑是一组代码,然后通过访问时的域名信息,我可以判断与不同客户数据库的连接情况,比如 a.com 到 db-a,c.com 到 db-c。此功能已实现。在集成 cap 时,我最初的想法是 cap 服务使用公共数据库,但现在我遇到了 cap 必须与客户业务相同的库的限制。因此,我想知道在代码启动时,我是否可以遍历并启动所有客户 dB 的上限服务。

CAP 当前不支持动态数据库切换。

            using (var scope = new TransactionScope())
            {
                using var db = new ClientDbContext();

                var x = new TCount();
                x.ClientSign = db.ClientSign;
                x.Count = 1;
                x.Id = Guid.NewGuid();
                x.CreateTime = DateTime.Now;

                db.TCount.Add(x);

                db.SaveChanges();

                cap.Publish("S", DateTime.Now);

                scope.Complete();
            }

我目前是这样做的,然后在 postgresql 配置中开启预处理事务,看起来不会造成什么 bug,效果就实现了。当最终事务提交时,cap 和 business db 的操作事务会统一提交,但这需要对 postgresql 进行修改。在 max_prepared_transactions = 100 的配置文件中,默认为 0 表示被禁用,但不清楚打开数据库的预处理事务,是否有任何未知的问题

TransactionScope

Did you find a workaround? 'TransactionScope' seems to depend on the DTC of Microsoft Windows, which is not supported by linux

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants