Commit Graph

309 Commits

Author SHA1 Message Date
Preston Guillory
9a0e20338d Catch name collisions within type (#184)
* Catch name collisions within type

If two names of the same type (for example, two structs) exist in the same
file, one of them will be discarded silently at parse time. This causes it to
raise an exception.

* Clean up exception message
2017-01-23 10:40:05 -08:00
Jon Parise
72632c75a3 Prepare the 1.3.2 release (#187)
This address some remaining Elixir 1.4 warnings, tweaks the docs, and
updates a few package dependencies.
2017-01-18 15:15:47 -08:00
Jon Parise
9d2ce55620 Reintroduce the 'thrift.generate' mix task (#186)
My previous attempt to consolidate these two mix tasks into one was
unsuccessful due to the way mix tasks receive their command line
arguments. Specifically, we don't have a good way to differentiate
between e.g. a `mix test` command line containing test script filenames
and a `mix compile.thrift` command line naming Thrift schema files. When
the `:thrift` compiler is included, it will also run in the `mix test`
task flow and get confused about its inputs.

We now have two distinct and purpose-built mix tasks:

 - `compile.thrift` - intended for use in the Mix.compilers list
 - `thrift.generate` - intended for interactive command-line use
2017-01-17 14:18:58 -08:00
Preston Guillory
4aab8763d2 Convert resolver from process to function (#183)
Previously the resolver was a separate process that just maintained a map. This
had the drawback that it was difficult to catch errors raised during the
resolution process. We'd to be able to raise such an error on name collisions.
2017-01-13 17:47:08 -08:00
Preston Guillory
151fd0c6f1 Support binary default values (#182)
* Support binary default values

* Check binary default value
2017-01-13 15:39:36 -08:00
Jon Parise
aa07d24c5a Consolidate binary protocol field type constants (#180)
We previously defined nearly identical sets of constants representing
the binary protocol's field types as attributes in each module that
required them. This duplication isn't great for long-term maintenance.

This approach defines a single set of type constants as macros in a
new Thrift.Protocol.Binary.Type module. Using macros lets us preserve
all of the compile-time benefits we were getting from the previous
approach while still supporting code sharing.
2017-01-13 13:30:44 -08:00
Jon Parise
39882a2957 Force coveralls.travis to run in the 'test' env (#178) 2017-01-12 10:20:56 -08:00
Preston Guillory
6b4a15f60f Make generated server opts optional (#176) 2017-01-11 13:39:05 -08:00
Steve Cohen
1f78c31055 Timeout / Retry refactor (#167)
* Timeout / Retry refactor

Servers now support read timeouts

Additionally, I changed how we handle retries due to some idiosyncracies
with how erlang responds to server failures.

When the server closes the connection, the client's `:gen_tcp.send`
operation will always succeed, failing instead on the corresponding
`:gen_tcp.recv` command. This is problematic, because we can't know for
sure that a message has been sent, and if we retry, we might resend a
message accidentally.

Furthermore, we can _never_ really know if a oneway message has been
sent or not.

Admittedly, the window for this is pretty narrow, the server would have
to sever the connection between the send and recv calls. The next case
is more troublesome.

Since we have backoff behavior, imagine if the user has set a retry
count of `:infinity` and made a call to a dead server. Now the client is
backing off and the `GenServer` call will timeout after 5 seconds. The
client is now stuck in a loop, reconnecting forever.

In light of these issues, I've removed repeated reconnects from the
client and have implemented a one-shot reconnect. We can still send a
message twice, but the window is sufficiently small to make me not worry
so much. This also has the effect of improving UX in the light of a
server that disconnects clients after a short timeout. If you send a
message on a disconnected client, it remembers it, reconnects and sends
it.

That seems reasonable.
2017-01-11 13:25:15 -08:00
Preston Guillory
c2a1f51475 Wrap long lines in generated output (#175)
Generated module names can be quite long, so this pattern produces very long
lines because Macro.to_string does not wrap pipe operators to the next line.

  serialized_var = %Big.Generated.Module{} |> Big.Generated.Module.serialize()

This change just replaces it with a slightly more readable:

  var = %Big.Generated.Module{}
  Big.GeneratedModule.serialize(var)
2017-01-11 11:47:05 -08:00
Jon Parise
658bf9f878 Use the latest .Client and .Server namespaces (#174)
Fixes #171
2017-01-11 09:08:29 -08:00
Ali Altaf
5d955839f7 Fixed incorrect code in README (#173) 2017-01-10 16:48:44 -08:00
Dan Swain
204254e4f6 Merge pull request #165 from dantswain/field_of_snakes
Ensure field names are valid elixir function names
2017-01-10 11:24:50 -05:00
Steve Cohen
592ff37c5b We moved the behaviour, example now reflects that (#169) 2017-01-09 17:31:47 -08:00
Steve Cohen
087724d5f9 Handled binary type in Behviour (#168)
The behaviour module didn't properly handle the binary type.
2017-01-09 17:31:36 -08:00
Jon Parise
8b1728294f Update dependencies for Elixir 1.4 compatibility (#166)
This are all relatively minor updates to newer releases, many of which
address new Elixir 1.4 warnings.
2017-01-08 10:00:27 -08:00
Dan Swain
e3c1af0056 Comment the atomic snake 2017-01-08 12:58:46 -05:00
Jon Parise
186663d600 Fix some warnings flagged by Elixir 1.4 (#164)
1. Unused module attributes
2. Variable vs. function name ambiguity
2017-01-08 08:57:49 -08:00
Dan Swain
31a2ca8474 Ensure field names are valid elixir function names
Closes #161
2017-01-08 09:31:36 -05:00
Preston Guillory
887be2f8b1 Make client start_link opts optional (#163) 2017-01-06 14:14:02 -08:00
Preston Guillory
abef5d995e Refactor Client generated/static interface (#158)
* Refactor Client generated/static interface

This moves message serialization completely into Binary.Framed.Client, and
response decoding completely out into the generated client. Their
responsibilities are more coherent. It also puts us into position for future
potential improvements, such as moving seq_id management into the connection
process's state, and generating code to match response exceptions in the way we
currently match unions.

* Return TApplicationException for invalid message type

* Keep seq_id in connection process state

* PR feedback
2017-01-06 10:04:00 -08:00
Preston Guillory
5cba75d22c Rename StructRef to TypeRef/ValueRef (#159)
* Rename StructRef to TypeRef/ValueRef

* Rebased onto thrift_tng
2017-01-06 10:03:33 -08:00
Preston Guillory
cc81ac3620 Ignore tmp directory (#160)
The tmp directory is used to store temporary .thrift and generated files by
ThriftTestCase. It's typically around during development and contains files but
they should not be checked in.
2017-01-06 04:34:51 -08:00
Preston Guillory
6bcdb81b1e Implement struct defaults (#154)
* Implement struct defaults

* Test empty defaults
2017-01-05 16:52:44 -08:00
Preston Guillory
a586a1a577 Implement deserialization of maps/sets/lists of binaries (#156)
Seems to have been overlooked. We implemented strings, which are effectively
the same in Elixir, but didn't check specifically for a type of :binary in
every situation.
2017-01-05 16:11:39 -08:00
Steve Cohen
77f22b75dd Server benchmark (#155)
* Added simple server benchmark

Updated README.md with benchmark results
2017-01-05 15:46:49 -08:00
Steve Cohen
4d15464fe2 Updated docs to reflect new packaging (#153) 2017-01-05 10:44:26 -08:00
Jon Parise
cc6028475a Test using the full Elixir 1.4.0 release (#152) 2017-01-05 09:44:13 -08:00
Preston Guillory
a49bbed2ef Allow integer defaults for double fields (#151) 2017-01-04 14:38:31 -08:00
Steve Cohen
1ee2ae9531 Changed Packaging (#148)
* Changed Packaging

Implements ideas in
https://github.com/pinterest/elixir-thrift/issues/144
2017-01-04 13:58:30 -08:00
Preston Guillory
23e83f55a2 Rename test for constant default values (#149)
I forgot to give it a proper name in #147.
2017-01-04 12:40:31 -08:00
Preston Guillory
2ef0edb7d2 Proofread README (#146)
- Fixed a few typos.
- Fixed output module paths.
- Change "IO list" references to "iodata" as seems to be preferred by Elixir docs.
2017-01-04 11:29:29 -08:00
Preston Guillory
30e27ff35e Generate const default values (#147)
Previously when the parser found a reference where it expected a static value,
it treated it as an enum. However it could also be a const. Now the parser
turns any reference into a StructRef and leaves it to the next layer to resolve
the reference.

Fixes #140.
2017-01-04 11:18:45 -08:00
Steve Cohen
d8eb83c684 Updated Readme with instructions for using Thrift. (#145)
* Updated Readme with instructions for using Thrift.
2017-01-04 09:34:25 -08:00
Steve Cohen
fd8600815d Booleans can have integer default values (#143)
Booleans can have 1 and 0 as default values. This converts them into
true and false, so we can deal with them properly.

Fixes #142
2017-01-03 14:18:47 -08:00
Jon Parise
9cd1d502a1 Rename service_module_name/2 to just module_name/2 (#141)
This avoids a bit of "stutter" because we always call this function via
the Service module namespace (e.g. `Service.module_name`).
2017-01-03 14:18:25 -08:00
Steve Cohen
910172c58f Server improvements (#139)
* Server improvements

The server's start_link didn't actually start_link. I've changed this to
bring the server's supervision into the user's application.

Also, we weren't properly cleaning up after server errors, so now I just crash.
2017-01-03 12:44:41 -08:00
Preston Guillory
c51fb22918 Allow 'default required' fields to be nil (#137)
* Allow 'default required' fields to be nil

We discovered that other Thrift implementations we use internally do not
serialize unset 'default required' fields. This change brings our
implementation's behavior in line with the others.

* Test that optional fields are serialized
2017-01-03 12:39:47 -08:00
Jon Parise
207a81356d Small improvements to the binary protocol type IDs (#132)
1. Fix the `type_id` typespec to use the correct value range.
2. Add a formal `@stop` type identifier (0) and use it below.
2017-01-03 09:32:22 -08:00
Dan Swain
5273c677b7 Handle empty and non-empty default containers (#135)
* Handle empty list and set defaults
2017-01-03 09:09:26 -08:00
Jon Parise
26c6f97df1 Always treat struct field IDs as ::16-signed (#133)
We were using using `::size(16)` in many cases, which is an unsigned
integer value. The specification says this should be a signed value.
2017-01-02 20:54:27 -08:00
Steve Cohen
96ed239ed9 Better exception handling (#131)
Not all exceptions have a message; they all play well with Exception.message though.
2017-01-02 20:53:12 -08:00
Steve Cohen
f2cb210282 Enum and union behaviours (#130)
* Added Enums and unions to behvaiour
2017-01-02 19:44:32 -08:00
Dan Swain
67a85df415 Merge pull request #128 from dantswain/syntax_errors
Raise a meaningful exception on parse errors
2017-01-02 22:16:13 -05:00
Dan Swain
e11eaabde1 More PR feedback 2017-01-02 22:12:09 -05:00
Dan Swain
852f7d9971 Merge branch 'thrift_tng' into syntax_errors 2017-01-02 22:10:34 -05:00
Jon Parise
579f4fd101 Minor improvements to the Thrift compile task (#129)
- Our command line options now more closely mimic the Apache Thrift
  compiler's. We support both long and "short" option formats.
- The compile task's output now simply prints "Compiling N files", which
  is the Elixir 1.3+ output convention. Use the `--verbose` command line
  option to see per-file output.
- The compiler task's unit test helper code has been simplified a bit.
2017-01-02 17:53:16 -08:00
Preston Guillory
8c81e90c5d Enforce field requiredness during serialization (#127)
Enforce field requiredness during serialization

The IDL spec [1] states that required fields must always be written during
serialization. There are also "default required" fields, i.e. fields specified
neither as required or optional. Apparently they also should always be written,
though there are exceptions to which the spec alludes but about which it does
not deign to elaborate.

[1]: https://thrift.apache.org/docs/idl#field-requiredness
2017-01-02 17:26:13 -08:00
Preston Guillory
35af4fea49 Require atom for StructGenerator.generate label (#125)
Require atom for StructGenerator.generate label

Previously its argument type was inconsistent, being sometimes a string and
other times an atom.
2017-01-02 16:21:04 -08:00
Jon Parise
fb2dfee7db Bump our minimum Elixir version to 1.3 (#126)
This gives us the ability to use 1.3+ APIs as we develop our 2.0 branch.
Many other libraries (Absinthe, Dialyxir) also have a 1.3+ requirement.

Also, Elixir 1.4 is imminent, so add that to our testing matrix too.
2017-01-02 14:32:46 -08:00