Skip to content

fix(engine): only start one engine for umbrella apps#462

Open
katafrakt wants to merge 3 commits intoelixir-lang:mainfrom
katafrakt:one-engine-for-umbrella
Open

fix(engine): only start one engine for umbrella apps#462
katafrakt wants to merge 3 commits intoelixir-lang:mainfrom
katafrakt:one-engine-for-umbrella

Conversation

@katafrakt
Copy link
Contributor

This adds check for being in an umbrella while determining the project the file belongs to. The detection mechanism is finding mix.exs with apps_path defined in project, which is the best I was able to come up with without actually evaluating mix.exs.

When going up in search of umbrella mix.exs, we put a boundary on the root of the currently open project, so opening individual apps separately is still possible (and we don't go spelunking through the filesystem).

fixes #460

@katafrakt katafrakt marked this pull request as ready for review February 26, 2026 12:07
@mhanberg
Copy link
Member

I'm kind of confused why so much specific code is required for this.

Shouldn't the way to determine the project is by comparing to the root_uri/workspace folder?

In Next LS that is how I dispatched requests/notifications to each engine node/document store

@katafrakt
Copy link
Contributor Author

Shouldn't the way to determine the project is by comparing to the root_uri/workspace folder?

There might be no mix project at this. This is quite common for monorepos actually.

@mhanberg
Copy link
Member

Shouldn't the way to determine the project is by comparing to the root_uri/workspace folder?

There might be no mix project at this. This is quite common for monorepos actually.

That is not what an umbrella app is tho. An umbrella app will have a project. And to clarify, i meant at the root of the workspace folder.

If someone opens a mono repo with 1 umbrella and 1 normal, you still just need to treat the umbrella as just an app

monorepo
- umbrella
    - mix.exs 
    - apps
        - child1
            - mix.exs
        - child2
            - mix.exs     
- normal
    - mix.exs

So for any file you check

# pseudo code, there would be more around absolute paths/etc
for project_path <- ["monorepo/umbrella", "monorepo/normal"] do
    String.starts_with?(file_uri, project_path)
end

@mhanberg
Copy link
Member

Basically, the editor tells us the root directories of each workspace (folder) and we need to route requests to them based on the file uri. I don't think there is much else to it.

@katafrakt
Copy link
Contributor Author

I'm opening my work monorepo now and it just sends one workspace folder:

"workspaceFolders":[{"uri":"file:///Users/pawel.sw/jump/Jump","name":"~/jump/Jump/"}]

The Elixir project is at ~/jump/Jump/api.

@mhanberg
Copy link
Member

I'm opening my work monorepo now and it just sends one workspace folder:


"workspaceFolders":[{"uri":"file:///Users/pawel.sw/jump/Jump","name":"~/jump/Jump/"}]

The Elixir project is at ~/jump/Jump/api.

You have to tell the editor the workspace folders, it doesn't automatically guess them.

@katafrakt
Copy link
Contributor Author

The thing is that I don't have to do it anymore. With automatic subprojects detection I just open one workspace folder and Expert finds a mix project in a subfolder.

@mhanberg
Copy link
Member

The thing is that I don't have to do it anymore. With automatic subprojects detection I just open one workspace folder and Expert finds a mix project in a subfolder.

I think there may be confusion as to what we are trying to fix here.

Are you implying we already have that? I am not under the impression that we do. That is what workspace folders are for.

@doorgan
Copy link
Collaborator

doorgan commented Feb 26, 2026

What happens today:

  • you start your editor at the umbrella root, and an engine is started for the umbrella
  • you open a file in a subapp, and an engine is started for the sub-app too

We're using mix.exs as a proxy for "mix project", when you open a file we walk the document uri upwards until we find a .exs file, and we create a project for that.
In an umbrella project, if you open a file in a subapp, we will find the .exs file for that sub-app, start an engine for it, and route all requests to that project, never to the umbrella engine

@katafrakt
Copy link
Contributor Author

yes, we have it I think since #18

@doorgan
Copy link
Collaborator

doorgan commented Feb 26, 2026

Yes, and that is what this PR is trying to fix. If we know you're at an umbrella, we'd need to start an engine for the umbrella root only.
I haven't extensively tested umbrellas bafere or after #18 so I'm not sure if having a single engine would affect completions. For example subapp A depends on subapp B, so A should get completions from B but B should not get completions from A

@mhanberg
Copy link
Member

In my opinion, we need to assume the root of the workspace folder is the root of the app with the mix.exs file and start the engine in there.

@katafrakt
Copy link
Contributor Author

katafrakt commented Feb 26, 2026

I'm not sure if having a single engine would affect completions. For example subapp A depends on subapp B, so A should get completions from B but B should not get completions from A

Yeah, great catch. One engine for the whole umbrella means shared indexer, so actually B gets completions from A. It actually works as you described (A gets completions from B, but B does not from A) currently, without the changes from this PR - and with starting a separate engine for every subapp. I think ElixirSense fallback simply resolves B as a dependency of A and that's why the completion works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Start only one engine for umbrella apps

3 participants