jsonkenl / xlsxir

Xlsx parser for the Elixir language.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Concurrent access fails.

brushbox opened this issue · comments

I am using Xlsxir from a phoenix application which means there will be the potential for multiple users to try and process their spreadsheets simultaneously.

But due to the global unzip dir (I think) and ets tables, concurrent access fails. This is evident when I run my tests. If they run async, I get failures. If I serialise them - they all pass.

The solution I came up with was to put a GenServer facade in front of Xlsxir. Calls to the facade are serialised via the GenServer's mailbox so xlsx processing only happens on one file at a time.

This is not ideal but it solves the initial problem. It may lead to a performance bottleneck in the (for me, far) future.

I was wondering whether it would be useful for this technique to be added to the documentation?

Here's an example of the GenServer:

defmodule Excel do
  use GenServer

  def start_link do
    GenServer.start_link(__MODULE__, :ok, name: :excel)
  end

  ## Public interface

  def from_xlsx(path) do
    GenServer.call(:excel, {:from_xlsx, path})
  end

  ## Server callbacks
  def handle_call({:from_xlsx, path}, _from, state) do
    {:reply, do_work(Xlsxir.multi_extract(path)), state}
  end 

  defp do_work({:error, _} = err), do: err
  defp do_work(tables) do
    res = process_tables(tables)
    tables |> Enum.each(fn {:ok, id} -> Xlsxir.close(id) end)

    res
  end

  ...

# Usage:
  # start the GenServer
  Excel.start_link

  # and in your app, use it:
  res = Excel.from_xlsx("path/to/file.xlsx")

That's my first GenServer - and I know it's a little odd because it doesn't actually care about state at all. I'm more than happy to hear feedback on whether the above is useful, not, or whether it is a "start" for something that may be useful.

Note: with the change to use the above pattern, my tests run successfully when running async.

I see that PR #52 may address these issues in a much better way. If that PR gets merged then I expect the above is of little use going forward.

Hey @brushbox, we are working to get #52 merged. If you can, please test it out once we do to verify it solves your problem. Thanks for detailing out the issues you're having.

#52 was merged, so please give it a shot to see if it fixes your issue. Closing for now, please re-open if you continue to have issues.