Elixir client for NetSuite's SuiteTalk SOAP API, with support for some built-in REST endpoints as well.
Ever seen this error before?
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>Only one request may be made against a session at a time</faultstring>
<detail>
<platformFaults:exceededRequestLimitFault xmlns:platformFaults="urn:faults_2012_1.platform.webservices.netsuite.com">
<platformFaults:code>WS_CONCUR_SESSION_DISALLWD</platformFaults:code>
<platformFaults:message>Only one request may be made against a session at a time</platformFaults:message>
</platformFaults:exceededRequestLimitFault>
<ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">sb-partners-java051.svale.netledger.com</ns1:hostname>
</detail>
</soapenv:Fault>
</soapenv:Body>
Out of the box, the SuiteTalk API does not allow concurrency. Given that it can take upwards of 2 seconds to fetch a single record (!), this is nothing short of depressing.
NetSuiteElixir aims to improve this. It allows you to store and draw from a pool of NetSuite credentials when making your requests. Simply set your configs here, and view the connection processes running them:
NetSuite.Connections.Pool.list
Did someone say OTP? Yes. Yes, please.
NetSuiteElixir offers first-class support for asynchronous requests through its connection pool. By default, all requests are kicked off to the pool and run in a separate process, and can be retrieved when they finish. Each API call returns a ticket (reference) that can be used to look up the result.
{:ok, ticket} = NetSuite.Rest.Roles.get
NetSuite.response(ticket)
=> {:pending, nil} # because the request isn't finished yet
# time passes ...
NetSuite.response(ticket)
=> {:ok, {200, [%{"account" => %{"internalId" => "TSTDRV12314", ... }
Want to use the connection pool but block the current process until your request completes? No problem:
{:ok, ticket} = NetSuite.Rest.Roles.get
NetSuite.wait_for_response(ticket)
=> {:ok, {200, [%{"account" => %{"internalId" => "TSTDRV12314", ... }
Have a bunch of requests that you want made with the same connection/credentials? Just pass them to NetSuite#call/1:
{:ok, ticket} = NetSuite.call(fn(config) ->
fulfillment = NetSuite.Records.ItemFulfillment.get(config, 827332)
sales_order = NetSuite.Records.SalesOrder.get(config, fulfillment.created_from)
NetSuite.Records.SalesOrder.delete(sales_order)
end)
Or, process them the old-fashioned way, one at a time by specifying the configs you want the request made with:
NetSuite.Rest.Roles.get(%NetSuite.Configuration{...})
=> {:ok, {200, [%{"account" => %{"internalId" => "TSTDRV12314", ... }
-
Add netsuite_elixir to your list of dependencies in
mix.exs
:def deps do [{:netsuite_elixir, github: "davidlaprade/netsuite_elixir"}] end
-
Ensure netsuite_elixir is started before your application:
def application do [applications: [:netsuite_elixir]] end
-
Run
mix deps.get
-
Compile:
mix compile
Load the app into the elixir REPL:
iex -S mix
Once in the REPL, set your credentials:
NetSuite.Configuration.set %{
email: ..., # String, required
password: ..., # String, required
account: ..., # String, optional
wsdl: ..., # String, optional but has default
api_version: ..., # String, optional but has default "2012_1"
production: true # Boolean, optional but defaults to true
}
Test that your credentials are working:
NetSuite.Rest.Roles.get