ekvedaras / laravel-query-intellij

πŸ’Ώ Laravel Query Builder integration for PhpStorm
MIT License
47 stars 3 forks source link

PhpStorm freeze #114

Open smirok opened 4 months ago

smirok commented 4 months ago

Hi! PhpStorm team is here!

We noticed that PhpStorm users experience freezes when using the "Laravel Query" plugin. The stack trace of the freeze is attached below. Most likely, the ReadAction called when initializing DbReferenceExpression takes too long.


Freeze for 40 seconds
IDE KILLED! Sampled time: 31900ms, sampling rate: 100ms, GC time: 177ms (0%), Class loading: 0%

The stack is from the thread that was blocking EDT
com.intellij.diagnostic.Freeze
    at java.base@17.0.10/jdk.internal.misc.Unsafe.park(Native Method)
    at java.base@17.0.10/java.util.concurrent.locks.LockSupport.park(LockSupport.java:341)
    at java.base@17.0.10/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:506)
    at java.base@17.0.10/java.util.concurrent.ForkJoinPool.compensatedBlock(ForkJoinPool.java:3451)
    at java.base@17.0.10/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3434)
    at java.base@17.0.10/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1623)
    at java.base@17.0.10/java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:420)
    at com.intellij.concurrency.JobLauncherImpl$2MyProcessQueueTask.lambda$call$0(JobLauncherImpl.java:486)
    at com.intellij.concurrency.JobLauncherImpl$2MyProcessQueueTask$$Lambda$5940/0x0000000802b1f650.run(Unknown Source)
    at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$13(CoreProgressManager.java:660)
    at com.intellij.openapi.progress.impl.CoreProgressManager$$Lambda$1465/0x000000080109e5d0.compute(Unknown Source)
    at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:684)
    at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:659)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:78)
    at com.intellij.concurrency.JobLauncherImpl$2MyProcessQueueTask.call(JobLauncherImpl.java:483)
    at com.intellij.concurrency.JobLauncherImpl$2MyProcessQueueTask.call(JobLauncherImpl.java:471)
    at java.base@17.0.10/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1428)
    at java.base@17.0.10/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
    at java.base@17.0.10/java.util.concurrent.ForkJoinPool.helpJoin(ForkJoinPool.java:1883)
    at java.base@17.0.10/java.util.concurrent.ForkJoinTask.awaitDone(ForkJoinTask.java:440)
    at java.base@17.0.10/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:687)
    at java.base@17.0.10/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159)
    at java.base@17.0.10/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173)
    at java.base@17.0.10/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
    at java.base@17.0.10/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at dev.ekvedaras.laravelquery.utils.ResolverForColumnMethods$withOnePart$1.invoke(DbReferenceResolver.kt:129)
    at dev.ekvedaras.laravelquery.utils.ResolverForColumnMethods$withOnePart$1.invoke(DbReferenceResolver.kt:124)
    at dev.ekvedaras.laravelquery.utils.ResolverForColumnMethods.withOnePart$lambda$0(DbReferenceResolver.kt:124)
    at dev.ekvedaras.laravelquery.utils.ResolverForColumnMethods$$Lambda$8826/0x00000008034c8990.accept(Unknown Source)
    at java.base@17.0.10/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base@17.0.10/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
    at java.base@17.0.10/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
    at java.base@17.0.10/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base@17.0.10/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
    at java.base@17.0.10/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
    at java.base@17.0.10/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
    at java.base@17.0.10/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:686)
    at java.base@17.0.10/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159)
    at java.base@17.0.10/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173)
    at java.base@17.0.10/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
    at java.base@17.0.10/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at dev.ekvedaras.laravelquery.utils.ResolverForColumnMethods.withOnePart(DbReferenceResolver.kt:124)
    at dev.ekvedaras.laravelquery.utils.ResolverForColumnMethods.resolve(DbReferenceResolver.kt:111)
    at dev.ekvedaras.laravelquery.utils.DbReferenceResolver.resolve(DbReferenceResolver.kt:33)
    at dev.ekvedaras.laravelquery.models.DbReferenceExpression._init_$lambda$1(DbReferenceExpression.kt:61)
    at dev.ekvedaras.laravelquery.models.DbReferenceExpression$$Lambda$8801/0x00000008034aeaf0.run(Unknown Source)
    at com.intellij.openapi.application.impl.RwLockHolder.runReadAction(RwLockHolder.kt:254)
    at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:833)
    at dev.ekvedaras.laravelquery.models.DbReferenceExpression.<init>(DbReferenceExpression.kt:59)
    at dev.ekvedaras.laravelquery.inspection.UnknownColumnInspection$buildVisitor$1.visitPhpStringLiteralExpression(UnknownColumnInspection.kt:50)
    at com.jetbrains.php.lang.psi.elements.impl.StringLiteralExpressionImpl.accept(StringLiteralExpressionImpl.java:45)
    at com.jetbrains.php.lang.psi.elements.impl.PhpPsiElementImpl.accept(PhpPsiElementImpl.java:117)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner$InspectionProblemHolder.visitElement(InspectionRunner.java:589)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner.processContext(InspectionRunner.java:408)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner.lambda$inspect$7(InspectionRunner.java:177)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner$$Lambda$6216/0x0000000802c8fbf0.run(Unknown Source)
    at com.intellij.openapi.application.impl.RwLockHolder.tryRunReadAction(RwLockHolder.kt:310)
    at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:951)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner.lambda$executeInImpatientReadAction$17(InspectionRunner.java:371)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner$$Lambda$6225/0x0000000802c924f0.compute(Unknown Source)
    at com.intellij.util.AstLoadingFilter.forceAllowTreeLoading(AstLoadingFilter.java:158)
    at com.intellij.util.AstLoadingFilter.forceAllowTreeLoading(AstLoadingFilter.java:150)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner.lambda$executeInImpatientReadAction$18(InspectionRunner.java:362)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner$$Lambda$6220/0x0000000802c91960.compute(Unknown Source)
    at com.intellij.util.AstLoadingFilter.disallowTreeLoading(AstLoadingFilter.java:129)
    at com.intellij.util.AstLoadingFilter.disallowTreeLoading(AstLoadingFilter.java:118)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner.executeInImpatientReadAction(InspectionRunner.java:362)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner.lambda$inspect$8(InspectionRunner.java:176)
    at com.intellij.codeInsight.daemon.impl.InspectionRunner$$Lambda$5892/0x0000000802aeb498.process(Unknown Source)
    at com.intellij.concurrency.JobLauncherImpl$2MyProcessQueueTask.lambda$call$0(JobLauncherImpl.java:494)
    at com.intellij.concurrency.JobLauncherImpl$2MyProcessQueueTask$$Lambda$5940/0x0000000802b1f650.run(Unknown Source)
    at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$13(CoreProgressManager.java:660)
    at com.intellij.openapi.progress.impl.CoreProgressManager$$Lambda$1465/0x000000080109e5d0.compute(Unknown Source)
    at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:735)
    at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:691)
    at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:659)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:78)
    at com.intellij.concurrency.JobLauncherImpl$2MyProcessQueueTask.call(JobLauncherImpl.java:483)
    at com.intellij.concurrency.JobLauncherImpl$2MyProcessQueueTask.call(JobLauncherImpl.java:471)
    at java.base@17.0.10/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1428)
    at java.base@17.0.10/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
    at java.base@17.0.10/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
    at java.base@17.0.10/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
    at java.base@17.0.10/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
    at java.base@17.0.10/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
ekvedaras commented 4 months ago

If only I would know how to address that πŸ˜„ Is your DB very big or something?

smirok commented 4 months ago

It isn't my stacktrace and I can't get any information about the DB size, but I do expect that the user's DB is quite large)

I can say that in this case, the UI thread required a write action, but was unable to obtain a write lock, as at that time, the heavy DbReferenceResolver.resolve operation was executed inside a runReadAction call on a background thread.

I assume there is no need to call runReadAction here if read access is allowed. It might be done otherwise, if it's necessary according to the code logic.

Something like this perhaps would work:

        if (!DumbService.isDumb(project)) {
            if (ApplicationManager.getApplication().isReadAccessAllowed) {
                TableAndAliasCollector(this).collect()
                DbReferenceResolver(this).resolve()
            } else { // if you need it
                ApplicationManager.getApplication().runReadAction {
                    TableAndAliasCollector(this).collect()
                    DbReferenceResolver(this).resolve()
                }
            }
        }

If it doesn't help, I would suggest using cancellable read actions (see https://plugins.jetbrains.com/docs/intellij/general-threading-rules.html#read-action-cancellability) or decomposing DbReferenceResolver.resolve into several steps and calling each of them as a separate runReadAction.

ekvedaras commented 4 months ago

Thanks, very helpful πŸ™‚ I will try your suggestion. If all checks pass, will release

smirok commented 4 months ago

One a second thought, I've realized that the code snippet from above doesn't prevent freezing, sorry for the confusion.

I definitely recommend then to use a ReadAction.nonBlocking() from https://plugins.jetbrains.com/docs/intellij/general-threading-rules.html#read-action-cancellability

ekvedaras commented 4 months ago

If I use something like this:

ReadAction.nonBlocking<Unit> {
    TableAndAliasCollector(this).collect()
    DbReferenceResolver(this).resolve()
}

it doesn't seem to run if I call myFixture.completeBasic() in tests. What am I missing?

smirok commented 4 months ago

Does this not run only in tests or in PhpStorm too?

HenkPoley commented 3 months ago

I'm seeing PhpStorm 2024.1 (241.14494.237) hanging when editing SQL INSERT INTO VALUEs.

E.g.:

DB::insert('INSERT INTO table (t_id, name, description) VALUES (**hang when typing here**)');

Disabled all downloaded plugins. Then slowly re-enabled all plugins not related to PHP, then a few of the PHP plugins, and finally the most relatedly looking (this plugin).

Still not seeing the hanging behaviour anymore. So I guess there is some race condition based on hooking ordering, influenced by what order you enabled the plugins. Still seems stable after PhpStorm restarts.

I don't think the per project .idea\laravel-query-settings.xml has any influence, since the file is unchanged since last year for me.

jayantisuthar commented 2 months ago

Facing the same issue, I can't even work 5 minutes on Phpstorm and it freezes. no click possible, can't even click or close the PhpStorm, every time force OS to close the application.

sneakyx commented 1 month ago

To the topic "race condition": for me, it seemed there is a relation between "AI Assistant" activated and not activated. When I tested the AI assistant for 7 days, I had many freezes. After the 7-days were over, my PHPStorm never freezes, regardless what I am doing. For test purposes I could activate the AI assistant again. Once activated, just less than 1 hour later I had the first freeze. Maybe it is the laravel plugin, but with more and more plugins activated the race condition seems to come more frequently.

pestretsov commented 1 month ago

Hi @ekvedaras! This is PhpStorm team again. Do you have any updates on this issue? We see more and more users reporting that Laravel Query plugin freezes the IDE completely for them.

ekvedaras commented 1 month ago

Hey, sorry, hectic life πŸ˜ƒ To be honest I don't have enough knowledge about the platform to know how to fix this πŸ™‚ It seems related to ReadAction call. I also do not experience this myself :/ Granted I don't use AI assistant, just those single line completions. That read action scans code to find related statements to understand the query being built and link it to the right symbols in database. Maybe AI assistant gives the scan more work than it would need or vice versa 🀷

smirok commented 1 month ago

Hi @ekvedaras! Have you tried the suggested approach?

ekvedaras commented 4 weeks ago

Hi @ekvedaras! Have you tried the suggested approach?

Not entirely sure what it suggests apart form making it idempotent. I will try to investigate a bit more tomorrow. If you have any more pointers, happy to hear them :)

ekvedaras commented 4 weeks ago

Have published v4.0.3 with a potential fix. It should be released soon.

andreigabreanu commented 4 weeks ago

Hello, With the plugin enabled and updated to 4.0.3 + latest phpstorm, I've got a freeze almost instantly when opened a file with database queries (and refreshed the database connection). With the plugin disabled, everything works ok.

P.S. the plugin is super useful so thanks for the work you are doing on it and it would be awesome if this issue got fixed

ekvedaras commented 3 weeks ago

In order to test in later versions of phpstorm it seems like I need to do a bunch of upgrades in the plugin. Obviously various things break left and right πŸ™ƒ Might take more time

ekvedaras commented 3 weeks ago

It was mentioned I think that it may relate to AI assistant being enabled. My trial is expired so no clue how to test with it... πŸ˜„ As much as I test, everything works with no freezing 🀷

jacobp3f commented 3 weeks ago

Hi, I just wanted to share my experience with PhpStorm freezing on Ubuntu.

Whenever it's completely frozen, I use the command kill -9 $(pgrep -f phpstorm) to force it to close.

I've noticed that the freezing issue occurs specifically when I open a private Laravel library. This library includes only "illuminate/support" in its composer.json and does not have a .env file, which means there's no database connection. I often manipulate query builders in this library, and the freeze consistently occurs within files containing a $query instance. This leads me to believe that the absence of a database connection might be triggering the freezes.

Uninstalling the "Laravel Query" plugin resolved the issue for me. I hope this information proves useful.

danielpetrica commented 3 weeks ago

Hi to provide more context. I've been redirected here from reddit.

As I'm using the https://github.com/roblesterjr04/EloquentSalesForce plugin, I think this may make it crash too as If I remember correctly I've experienced these freezes only on the project where this plugin is used. Can it be that it times out because it can't reach salesforce to perform the query.

ekvedaras commented 2 weeks ago

Let's see if v4.0.4 helps

DmitrySkibitsky commented 2 weeks ago

Unfortunately it didn't work in my case. I enabled the plugin, updated it from version 4.0.2 to 4.0.4 and restarted the IDE. After clicking Refresh on the Database tab to see the new tables and interface ide hangs on all open windows. This is so sad.

ekvedaras commented 2 weeks ago

Well, I'm out of options then πŸ˜„ I cannot reproduce and clearly do not have enough knowledge about this platform nor kotlin/java dev in general to find the issue. I know the code there is not the best, but without help I don't know what else to try πŸ™‚ Find smart friends and send them here please πŸ™‚

smirok commented 1 week ago

@DmitrySkibitsky Hi! This is PhpStorm team once again. I was wondering if you encountered freezing issues when working with a local or remote database. Also, could you please provide me with an approximate estimate of the size of your database?

DmitrySkibitsky commented 1 week ago

@DmitrySkibitsky Hi! This is PhpStorm team once again. I was wondering if you encountered freezing issues when working with a local or remote database. Also, could you please provide me with an approximate estimate of the size of your database?

This is a local database with 400+ tables, some number of db views (less than 50). The size of databases is from 400mb to 3gb. If you need exact values, I can open a specific project that I am working on all the time, turn on the plugin, trigger a hang and provide exact values.

andreigabreanu commented 1 week ago

I can confirm it still freezes: this time I was in a class which has queries on the DB and I cmd+click a method to go to the definition. It jumped to the other file and everything froze.