-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Optional type as return value of parser calls #51
Comments
@julik I would like to implement this. So here is a code snippet. Here I just return the errors in a hash if the strategy is STRATEGIES = %i[all_results first_result]
def self.parse(io, natures: @parsers_per_nature.keys, formats: @parsers_per_format.keys, strategy: :all_results)
# Check for strategy
unless STRATEGIES.include? strategy
throw ArgumentError.new(
"Uknown strategy #{strategy}. Supported strategies: #{STRATEGIES}."
)
end
# If the cache is preconfigured do not apply an extra layer. It is going
# to be preconfigured when using parse_http.
io = Care::IOWrapper.new(io) unless io.is_a?(Care::IOWrapper)
# Always instantiate parsers fresh for each input, since they might
# contain instance variables which otherwise would have to be reset
# between invocations, and would complicate threading situations
parsers = parsers_for(natures, formats)
parser_errors = {}
results = parsers.lazy.map do |parser|
# We need to rewind for each parser, anew
io.seek(0)
# Limit how many operations the parser can perform
limited_io = ReadLimiter.new(io, max_bytes: MAX_BYTES, max_reads: MAX_READS, max_seeks: MAX_SEEKS)
begin
parser.call(limited_io)
rescue => error
parser_errors[parser.class.name] = error
nil
end
end.reject(&:nil?)
return results.first if strategy == :first_result
{
results: results.to_a,
errors: parser_errors
}
end Could you comment on it? |
Good question. Something like this: https://github.com/WeTransfer/image_vise/blob/master/lib/image_vise/render_engine.rb#L83 In other words, we can have a situation where parsers A and B return a valid result, and parser C errors out. In that case, we need to have some way to communicate that parser C failed to the caller, and maybe use a global FormatParser-configured hook for reporting the error, say, to Appsignal. So by "registering" I mean "communicating". Your idea seems nice, however I think we should return a more "monadic" flat list of parsers + their results or errors. Something like a sum type for |
@julik So each parser would return either a Should this result be encapsulated in a {
result: safe_parse(parser, limited_io) # returns either StandardError, Result or nil
parser: parser.class.name
} Should the |
@WJWH I know what you will say, but we might be needing a sum type or a monad here. Ideas? |
We call parsers in succession, and a single parser failing should not, at least for most errors, lead to other parsers failing as well. We currently capture a tiny subset of errors in the
.parse
method of the FormatParser module, but there is no guarantee these are the only errors a parser could raise.I think what we could use something like this instead:
For this we only have to introduce one wrapper method, and we don't have to change the parsers at all.
The text was updated successfully, but these errors were encountered: