Code Monkey home page Code Monkey logo

Comments (5)

rakuyoMo avatar rakuyoMo commented on June 2, 2024

In later attempts, I set allowsUnsafeTransactions to true

But I found that when writeWithoutTransaction or asyncWriteWithoutTransaction is executed, SchedulingWatchdog is released, and its life cycle only exists within the closure of the above method. This results in me being unable to use the db object within the trailing closure of saveImage.

Does this mean that no matter what method, I can't take db to other places?

from grdb.swift.

groue avatar groue commented on June 2, 2024

Hello @rakuyoMo,

Does this mean that no matter what method, I can't take db to other places?

That's exactly it. The documentation of asyncWriteWithoutTransaction(_:) states:

The Database argument to the updates closure argument is valid only during the execution of the closure. Do not store or return the database connection for later use.

This constraint currently lives in the documentation. As soon as the Swift language makes it possible to declare that some values can't be escaped, GRDB will make sure the sample code does not even compile.

If you want to perform further database operations, perform another database access.

In later attempts, I set allowsUnsafeTransactions to true.

It is not easy to perform two writes in two distinct persistence systems, and recover from an error in one of them. It's even more difficult when one of the system is asynchronous (saveImage).

I can't really provide advice on your best way to solve this. Just remember that GRDB transactions like to be synchronous. You can try to make them asynchronous with allowsUnsafeTransactions, but things will just turn more difficult. In particular, concurrent database access to the same DatabaseQueue might interfere in really bad ways. You might avoid this by using a specific DatabaseQueue instance. But now you'll face the risk of busy errors (due to the risk of parallel writes), and lose database observation (due to multiple connection instances). Pick up your battle wisely.

from grdb.swift.

rakuyoMo avatar rakuyoMo commented on June 2, 2024

Just remember that GRDB transactions like to be synchronous.

When I use the writeWithoutTransaction method, even though the trailing closure of saveImage and try db.beginTransaction() are executed in the main thread, SchedulingWatchdog will still be released because of a thread switch in the middle.

In fact, when I comment out the code that prevents me from performing the operation, the database can be written to normally, does this mean that this is just a risky operation and it is not absolutely dangerous?

does this mean that this is just a risky operation and it is not absolutely dangerous?

Well, I think it's an unrealistic idea, and just being risky is enough for it to be banned. At least this is not how the issue should be described or led in this direction.


@groue Or is there a way to achieve the following:

  1. After allowing back to the thread that created the database connection, add a new SchedulingWatchdog object.

    Use the writeWithoutTransaction synchronization method to create a connection on the main thread, because the thread will not be released, the program just switches between different threads, and will eventually return to the main thread, so you can try to re-add the SchedulingWatchdog object?

  2. Regarding the asyncWriteWithoutTransaction method, similarly, if the thread that creates the database connection is not released after switching threads, can the SchedulingWatchdog object be restored when we return to this thread?

from grdb.swift.

rakuyoMo avatar rakuyoMo commented on June 2, 2024

Can you provide some clues as to when SchedulingWatchdog will be released? Or I could figure out a way to keep it there.

from grdb.swift.

groue avatar groue commented on June 2, 2024

Just remember that GRDB transactions like to be synchronous.

I should have said it differently. When you perform a database access, whether it is synchronous or asynchronous, database operations are always executed in a closure that accepts a Database argument. This closure is synchronous. You must not perform async work there - at least no async work that escapes the Database from the closure.

This is how it works. This is explicitly documented, as I mentioned above. This will not change.

I'm not sure it is useful to focus of SchedulingWatchdog, which is an internal tool. Its goal is to help detect misuses of a Database, such as escaping it. If it prevents you from using the db value from the saveImage completion block, well that's exactly its job.

As I said above:

It is not easy to perform two writes in two distinct persistence systems, and recover from an error in one of them. It's even more difficult when one of the system is asynchronous (saveImage).

You can try to keep on bending GRDB into supporting unsafe operations, but, again, as I said above:

Pick up your battle wisely.

For example, did you consider refactoring saveImage into a synchronous method? Or did you consider performing an asynchronous call to saveImage and then one single database access in its completion block? Or to perform two transactions (one before and one after saveImage)?

Anyway: as long as you try to perform an async operation in the middle of one single database transaction, you'll face difficulties that GRDB has no intention to help dealing with. This would be against all the concurrency safety measures provided by the library, which aim at the safety of your user's data. Either refactor your code, or live with unsupported techniques that might break any time.

from grdb.swift.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.