<FromGitter>
<kingsleyh> I've got a heredoc with a string interpolation inside and crystal tool format complains - anyway to ignore this during format? or how to fix it?
<FromGitter>
<kingsleyh> expecting DELIMITER_START, not `CONST, SUFFIX`,
<FromGitter>
<kingsleyh> when SUFFIX is the interpolated string
<FromGitter>
<kingsleyh> @asterite yeah indenting did fix it
_whitelogger has joined #crystal-lang
deavmi_ has quit [Quit: Eish! Load shedding.]
f1refly has quit [Quit: bye fags]
f1refly has joined #crystal-lang
deavmi has joined #crystal-lang
zorp_ has joined #crystal-lang
[gnubie] has joined #crystal-lang
[gnubie] has quit [Ping timeout: 260 seconds]
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
<FromGitter>
<riffraff169> hello, im trying to use OptionParser, but it isnt working as i think it should...maybe im doing something wrong
<FromGitter>
<riffraff169> OptionParser.parse do |parser| ⏎ parser.banner = "Usage: compile65xx -f filename" ⏎ parser.on("-f", "--filename", "Source file") { |x| puts x; filename = x } ⏎ parser.on("-o", "--out", "Output file") { |name| outfile = name } ⏎ parser.on("-h", "--help", "Show this help") do ... [https://gitter.im/crystal-lang/crystal?at=5f53d7029566774dfe575719]
<FromGitter>
<riffraff169> hmm, never used gitter, how do i do code? not ``` it looks like
<FromGitter>
<Blacksmoke16> it is, but they have to be on their own line
<FromGitter>
<riffraff169> anyway, running: ./main -f file.dat, x (for option -f) is blank....but ./main -ffile.dat gets file.dat
<FromGitter>
<riffraff169> there should be able to be a space between -f and data (file.dat), but it just gets the space
<FromGitter>
<Blacksmoke16> do like `parser.on("-f FILE", "--filename FILE", "Source file") ...`
<FromGitter>
<riffraff169> hmm, interesting...i didnt quite get that from the documentation....if i did -ffile.dat, it worked, even without that extra data in the string....weird
<FromGitter>
<riffraff169> ok thanks
<FromGitter>
<riffraff169> decided to change a data type, getting something weird
<FromGitter>
<riffraff169> tokens = [] of Array(String|Int32|Symbol)
<FromGitter>
<riffraff169> which it is, [:val,12] and others
<FromGitter>
<Blacksmoke16> whats the reasoning for using a symbol over a string/
<FromGitter>
<riffraff169> well, i have the string a lot, it is an array of [:symbol, value]
<FromGitter>
<riffraff169> so there could be ["val", 12], ["val", 24], etc....wont a symbol be only once, but a string could have multiple copies in memory?
<FromGitter>
<riffraff169> and will a symbol compare be better than a string compare?
<FromGitter>
<Blacksmoke16> symbols are essentially numbers, so probably?
<FromGitter>
<riffraff169> yeah, so my other routine that takes tokens as input:
<FromGitter>
<riffraff169> thanks, give me a moment
<FromGitter>
<riffraff169> never mind, im stupid...missed another declaration somewhere else
<FromGitter>
<Blacksmoke16> 👍
<FromGitter>
<riffraff169> just need to talk out loud with someone
<FromGitter>
<riffraff169> so, i feel im having to declare the types several times...once before calling the function, so it can get the return value, once in the function that adds values to the array, and another in a function that uses that result
<FromGitter>
<riffraff169> then `@tokens = Tokens`
<FromGitter>
<Blacksmoke16> `@tokens : Tokens`
<FromGitter>
<Blacksmoke16> its a type, not a value
<FromGitter>
<riffraff169> ah yes....so then `@tokens : Tokens = []`, or `@tokens = [] of Tokens`
<FromGitter>
<Blacksmoke16> yea
<FromGitter>
<riffraff169> this is a project question...so you run `crystal init project_name`
<FromGitter>
<riffraff169> it creates the entire structure...you have the src dir, and the toplevel
<FromGitter>
<riffraff169> do you build in the src dir or the toplevel? do you use like rusts .toml file, or something else to specify the project information?
<FromGitter>
<riffraff169> is there good documentation on that? im running `crystal build src/main.cr`, but that is probably not correct
<FromGitter>
<Blacksmoke16> then you can do `shards build`
<FromGitter>
<riffraff169> it creates `main` (havent bothered changing output filename yet), but all my requires have to have `./somefile.cr`
<FromGitter>
<riffraff169> so a shard is not a library (or not only a library)
<FromGitter>
<riffraff169> but could create executables...that may have been my confusion
<FromGitter>
<riffraff169> thanks
<FromGitter>
<Blacksmoke16> a shard can either be an app or lib
<FromGitter>
<riffraff169> ah great, ill look into that, thanks
<FromGitter>
<Blacksmoke16> lib is essentially the same as an app, but w/o a .lock file
<FromGitter>
<Blacksmoke16> and prob some other minor differences
<FromGitter>
<riffraff169> newbie questions sorry, ive only started actually writing crystal a few days ago
<FromGitter>
<Blacksmoke16> np
go|dfish has quit [Quit: WeeChat 1.4]
go|dfish has joined #crystal-lang
<FromGitter>
<Blacksmoke16> so heres a concurrency conundrum im facing
<FromGitter>
<Blacksmoke16> im spawning n fibers to handle processing some data
<FromGitter>
<Blacksmoke16> each fiber will make x http requests
<FromGitter>
<Blacksmoke16> among other things
<FromGitter>
<Blacksmoke16> however the api im hitting up has an error limit, which i'll reach at some point
<FromGitter>
<Blacksmoke16> at which point i need to pause the requests until the error limit has reset
<FromGitter>
<Blacksmoke16> but i cant just sleep as there are other fibers executing, so i imagine i need some wrapper/manager to handle pausing all the fibers
<FromGitter>
<Blacksmoke16> or a different approach...
<FromGitter>
<riffraff169> is that an actual error limit, or an api request limit per minute type of thing? i encountered that once
<FromGitter>
<j8r> an error limit, or rate limit?
<FromGitter>
<j8r> Won't be better to fix this errors?
<FromGitter>
<j8r> for rate limiting, if it is IP based, it can be possible to trick it
postmodern has joined #crystal-lang
<postmodern>
is it possible to sub-class Module like in Ruby so you can do `include MyMixing.new(foo: 1, bar: 2, ...)`?
<postmodern>
not seeing a Module class in the documentation either
<postmodern>
besides LLVM::Module of course, but that looks like it's internal
<FromGitter>
<Blacksmoke16> its errors per minute
<FromGitter>
<Blacksmoke16> > Won't be better to fix this errors? ⏎ ⏎ I cant tho
<FromGitter>
<Blacksmoke16> the initial request i make is for a list of contracts, each of which has a starting location id
<FromGitter>
<Blacksmoke16> however i dont know if i have access to that location without making a request
<FromGitter>
<Blacksmoke16> which if i dont then it 403s and i get hit with an error
<FromGitter>
<Blacksmoke16> i thought about saving these locations to another table that i could use to know not to look them up again, but still would face the same problem initially as i need to make the requests to know
<FromGitter>
<j8r> what is the goal of this?
<FromGitter>
<Blacksmoke16> basically syncing data from an external API to my db
<FromGitter>
<j8r> and, why you have sometimes access and sometimes not?
<FromGitter>
<Blacksmoke16> data is from a game, just a limitation of the API
<FromGitter>
<Blacksmoke16> as to not leak data
<FromGitter>
<Blacksmoke16> like even tho the name/system of the location is public in game, its just not resolvable via the API if you don't actually have access to it :shrug:
<FromGitter>
<j8r> ok
<FromGitter>
<j8r> The error limit is linked to the API key, I guess?
<FromGitter>
<Blacksmoke16> probably?
<FromGitter>
<Blacksmoke16> im thinking i might be able to use a buffered error channel with `select`? when the buffer is full would switch to that `when` block then just sleep a minute
<FromGitter>
<j8r> that's not a public API
<FromGitter>
<Blacksmoke16> i didnt say it was
<FromGitter>
<j8r> so yeah, if it requires an API key they can simply base their rate limit to it
<FromGitter>
<j8r> no way to trick it
<FromGitter>
<Blacksmoke16> yea, i just need to backoff when im getting close to the error limits
<FromGitter>
<Blacksmoke16> the endpoint itself isnt rate limited, just are only allowed 100 errors per minute :/
<FromGitter>
<j8r> you could count the errors then
<FromGitter>
<Blacksmoke16> it comes back in header, so i always know how many i have left
<FromGitter>
<Blacksmoke16> but that just switches to another fiber and does more requests and ends up hitting the limit anyway since the fibers are independent
<FromGitter>
<Blacksmoke16> like 100 and some
<FromGitter>
<j8r> got an idea
<FromGitter>
<j8r> each time any part of the code, including in fibers, do an API request
<FromGitter>
<j8r> it goes through a method, that checks if the error limit is reached
<FromGitter>
<j8r> otherwise, it sleeps, like in you code snippet above
<FromGitter>
<j8r> perhaps that how you actually do?
<FromGitter>
<jwoertink> I need to boot an HTTP::Server during my specs where I'm calling `spawn { server.listen }`. I'm running in to an issue where my specs are running before the server is booted... Anyone have any suggestions on how to handle that better?
<FromGitter>
<Blacksmoke16> that method looks familiar :p
<FromGitter>
<j8r> haha, inspired by Athena TM
<FromGitter>
<jwoertink> ah, you're doing a sleep too
<FromGitter>
<Blacksmoke16> yea gives server time to start
<FromGitter>
<jwoertink> that's how I'm getting it to pass currently. I guess that's just what we have to do
<FromGitter>
<j8r> could use a channel too
<FromGitter>
<j8r> could be overkill
<FromGitter>
<Blacksmoke16> @j8r the main problem i think is atm the sleep causes it to just switch to another fiber which continues to execute more requests before sleeping itself, e.x.
<FromGitter>
<j8r> @Blacksmoke16 but that's good, no?
<FromGitter>
<j8r> Other fibers will continue, call the method, and directly sleep
<FromGitter>
<j8r> Ha ok you do a request each time to know the rate limit
<FromGitter>
<Blacksmoke16> yea, atm the method is *after* the request
<FromGitter>
<j8r> the state should be stored somewhere
<FromGitter>
<Blacksmoke16> i tried using a class var and have the sleep before the request, that didnt seem to help either
<FromGitter>
<Blacksmoke16> what you think about ⏎ ⏎ > im thinking i might be able to use a buffered error channel with `select`? when the buffer is full would switch to that `when` block then just sleep a minute
<FromGitter>
<Blacksmoke16> or would that have the same problem because sleeping in the main fiber within the select would end up switching to another fiber anyway...
<FromGitter>
<j8r> It will work?
<FromGitter>
<j8r> Yea, not sure it will do, but can be
<FromGitter>
<Blacksmoke16> ill have to play around wit hit
<FromGitter>
<Blacksmoke16> otherwise might be able to like defer the location requests until last and do them with a bit diff logic
<FromGitter>
<j8r> a logic like that, I tried to emulate the rate limit
<FromGitter>
<Blacksmoke16> hmm, yea maybe i need like a `Client`
<FromGitter>
<Blacksmoke16> to contain this logic
<FromGitter>
<j8r> @jwoertink you could have the server.start yield something, and inside the block a channel that sends a value to unblock a `channel.receive?`
<FromGitter>
<j8r> won't be perfect, because of done just before `bind` :/
<FromGitter>
<Blacksmoke16> @j8r didnt seem to help