<FromGitter>
<stern0> Back to my question. Do fibers use just one core or can use multiple cores
<FromGitter>
<j8r> One, that's the principle
<FromGitter>
<j8r> You can have concurency in one core, unless a process use 100% CPU time
<FromGitter>
<j8r> If this happen, all will be slowed of course
<FromGitter>
<straight-shoota> @stern0 You said it yourself, Crystal has no multithreading support yet. So all fibers are on only one core at the time.
g-glitch has quit [Remote host closed the connection]
rohitpaulk has joined #crystal-lang
rohitpaulk has quit [Ping timeout: 256 seconds]
<FromGitter>
<Blacksmoke16> having an issue merging hashes
<FromGitter>
<Blacksmoke16> where when i go to merge it gives me a variable must be Hash(String, ...)
<FromGitter>
<bew> instead of `@endpoints = @endpoints.merge(s)` you can do `@endpoints.merge!(s)` (with a bang `!`) to mutate the hash directly without creating a new one
<FromGitter>
<bew> in `construct_obj`, instead of making a lot of `@obj[path_name][...]` you can save `@obj[path_name]` in a local var, and use it (less `Hash#[]` call the better :) )
<FromGitter>
<bew> like `@obj[path_name] = my_hash = {} of String => PathObjBody`
<FromGitter>
<bew> and use `my_hash` later, it'll be the same as doing `@obj[path_name]` each time
<FromGitter>
<bew> why your hash in this method is not a class btw?
<FromGitter>
<bew> with description, parameters, path, scope, summary & version
<FromGitter>
<Blacksmoke16> it is i just excluded it from the paste
<FromGitter>
<Blacksmoke16> its in the one up a bit
<FromGitter>
<bew> I mean, why build a hash instead of build an object?
<FromGitter>
<Blacksmoke16> hm good question
<FromGitter>
<Blacksmoke16> probably could do
<FromGitter>
<bew> and to get back to your problem, you're trying to merge a `Hash(String, PathObjBody)` with a `Hash(String, Hash(String, PathObjBody))`
<FromGitter>
<j8r> How can improve this? `caddy.sections[0] = caddy.sections[0].merge({root: "/path"}) `
<FromGitter>
<bew> @Blacksmoke16 the merged type is `Hash(String, PathObjBody | Hash(String, PathObjBody))`, with the alias expanded
<FromGitter>
<bew> that the error you got, 'cause you're trying to store that type in `@endpoints` which is `Hash(String, PathObjBody)` only
<FromGitter>
<bew> @j8r what are the types here?
<FromGitter>
<bew> oh just use `merge!` ?
<FromGitter>
<bew> to mutate the thing directly
<FromGitter>
<bew> instead of building a new one
<FromGitter>
<bew> (if it's a hash or sth)
<FromGitter>
<Blacksmoke16> why would it work as a local variable tho?
<FromGitter>
<bew> @Blacksmoke16 I guess it's because the local variable happily accept any type, and is not constrained to a specific type
<FromGitter>
<j8r> I can do `klass.section[0][:test]["a"] = "C"` but not `klass.section[0][:root] = "C"`
rohitpaulk has quit [Ping timeout: 260 seconds]
<FromGitter>
<girng> i love me some namedtuples
<FromGitter>
<bew> @j8r yeah that's normal, string are immutable, so you need to modify the namedtuple to change it
<FromGitter>
<bew> but the hash is mutable, you can change the hash without having to make a new one
duper has quit [Remote host closed the connection]
wmoxam has quit [Remote host closed the connection]
<FromGitter>
<Blacksmoke16> @bew i refactored/rearranged some stuff so that the hash is now an object, and the @endpoints property is an array of that obj
<FromGitter>
<Blacksmoke16> thinking i can then just use a custom to_json to parse that array into the format i need
<FromGitter>
<bew> a mapping you mean?
<FromGitter>
<Blacksmoke16> mm sec
<FromGitter>
<Blacksmoke16> had a change of thought
<FromGitter>
<Blacksmoke16> yea nvm,
<FromGitter>
<Blacksmoke16> refactored it to use an obj and did `property endpoints = {} of String => EndpointObj`
<FromGitter>
<Blacksmoke16> which i update by doing `@endpoints.merge!(s)`
<FromGitter>
<Blacksmoke16> im happy with it
<FromGitter>
<Blacksmoke16> hardest part is figuring out what to call all these :(
<FromGitter>
<Blacksmoke16> i also just realized there was absolutely no point of me creating the hash array for parameters, since it was literally just an around about way of doing Parameter.to_h
<FromGitter>
<bew> simply doing `{y => z}` will create a hash
<FromGitter>
<bew> and you don't need a hash, you just want to set a value I think
<FromGitter>
<Blacksmoke16> correct
<FromGitter>
<Blacksmoke16> makes sense, one less hash so be more performant
<FromGitter>
<Blacksmoke16> here's a question, now that im using `Hash(String, EndpointObj)` as my endpoints variable, what if i needed to get the whole hash into json?
<FromGitter>
<Blacksmoke16> should just be able to make a custom to_json on the EndpointObj class?
<FromGitter>
<bew> yeah with a mapping
<FromGitter>
<bew> (for example)
<FromGitter>
<Blacksmoke16> also does inline if/unless not handle nil values? such as `@scopes << path.scope unless path.scope.nil?` yells saying scopes is string only while that is String | Nil
<FromGitter>
<galvertez> if that condition would ever return true during runtime then the type would be `String|Nil` regardless wouldn't it?
<FromGitter>
<Blacksmoke16> probably but shouldnt matter because the insert should never happen if it is nil?
<FromGitter>
<bew> the same way it does with a normal if
<FromGitter>
<bew> maybe `path.scope` will return something else on the second call
<FromGitter>
<bew> this way only one call to `path.scope` is made
<FromGitter>
<bew> and that result (which we know won't change) is inserted in `@scopes`
<FromGitter>
<galvertez> would using `#nil?` not add Nil to the type inference? JSON.mapping is just a macro it's not the final word on that instance variable's type
<FromGitter>
<bew> @galvertez hmm no? you can do `a = true; a.nil?; typeof(a)` it'll be `Bool`
<FromGitter>
<bew> `nil?` is just a method call, it doesn't do anything else
<FromGitter>
<bew> the compiler is just smart about `nil?` in conditions to *reduce* the type when it can
<FromGitter>
<Multipixelone> Okay so I have an array named "chocolate" How can I add everything in the array into a text file, on separate lines?
<FromGitter>
<bew> you could open a file, then for each element of the array: write the element to the file, then add a newline, until the end of the array
<FromGitter>
<JannAnthonyBriza> Having these problem already did `shards install`
<FromGitter>
<JannAnthonyBriza> kind a weird it was running yesterday :(
<FromGitter>
<bew> what's the full error? (the useful bits are at the bottom)
<FromGitter>
<JannAnthonyBriza> wait i'll try to screenshot the whole error, cause it does not fit in screenshot
<FromGitter>
<bew> no need to screenshot, just copy/paste the error to a pastebin or sth!
<FromGitter>
<JannAnthonyBriza> oh wait i this this is the problem ` /home/jann/.cache/crystal/usr-share-crystal-src-ecr-process.cr/macro_run: error while loading shared libraries: libevent-2.0.so.5: cannot open shared object file: No such file or directory`
<FromGitter>
<bew> yes!
<FromGitter>
<JannAnthonyBriza> yes i need to find this library `libevent-2.0.so.5:`
<FromGitter>
<bew> how did you installed crystal?
<FromGitter>
<JannAnthonyBriza> git this error when i upgraded my linux os from 16.04 to 18.04
<FromGitter>
<JannAnthonyBriza> i will try to uninstall my crystal
<FromGitter>
<faustinoaq> @JannAnthonyBriza Just try to search a similar file in your system using `sudo find / -iname "*libevent-2.0.so*"` and then create a symlink to it using `sudo ln -s /path/to/available/lib/libevent-2.0.so.X /usr/lib/libevent-2.0.so.5`
<FromGitter>
<faustinoaq> this is a common issue on dynamic linked executable's, sometimes the `.so` dependencies have version mismatch, although, commonly you can just point your missing lib to the available version in your system 😅
<FromGitter>
<faustinoaq> Also ensure first you have the right libs installed like @bew said
<FromGitter>
<Multipixelone> If I don't know how to do something, where is the best place to look? The API documentation seems pretty bare
<FromGitter>
<Multipixelone> Most of my learning has been "How do I do this in Ruby?" "Does it work in Crystal?" "Great!"
<FromGitter>
<epergo> crystal for rubyist by sdogruyol is a good resource to learn
<FromGitter>
<oprypin> @faustinoaq manually putting anything in /usr/lib basically means breaking your system. don't recommend people to break their system.
Ven`` has joined #crystal-lang
Ven`` has quit [Read error: Connection reset by peer]
Ven`` has joined #crystal-lang
<wuehlmaus>
say, i have the file "/etc/passwd". How do i get the creation time? with fileinfo i don't find the answer.
<wuehlmaus>
File.info("/etc/passwd") has st_ctimespec=LibC::Timespec
sz0 has quit [Quit: Connection closed for inactivity]
Ven`` has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
rohitpaulk has quit [Ping timeout: 256 seconds]
rohitpaulk has joined #crystal-lang
<FromGitter>
<sdogruyol> what'd be the most idiomatic way of running something periodically
<FromGitter>
<gdotdesign> how can I construct a `Hash(String, String | Int32)` from `{ "test" => "test"}`? Because the latter will just be `Hash(String, String)` which gives a type error, casting it does not help either.
<FromGitter>
<gdotdesign> right now I'm doing this `{ "test" => "test", "" => 0}` which feels like a hack
<FromGitter>
<yxhuvud> `{ "test" => "test"} of String => String|Int32` or something like that.
<FromGitter>
<gdotdesign> yes! that works thank you :D
alex`` has quit [Quit: WeeChat 2.1]
alex`` has joined #crystal-lang
alex`` is now known as alexherbo2
alexherbo2 is now known as alex``
<FromGitter>
<Blacksmoke16> @bew adding a JSON mapping worked perfect
<FromGitter>
<Blacksmoke16> thats super slick
<FromGitter>
<Blacksmoke16> is there a way to override the `setter: true` default behavior of JSON.mapping?
<FromGitter>
<faustinoaq> @oprypin What do you do when your have version mismatch on dynamic libs? (`.so` files) ? 😅
Raimondi has joined #crystal-lang
<FromGitter>
<schoening> Crystals concurrency is inspired by Go right? So wouldn't it perhaps also have made sense to have go style error returns? This is just a random question out of interest..
<FromGitter>
<faustinoaq> @schoening I guess crystal is inspired by ruby as well 😉
<FromGitter>
<schoening> Hehe yeah I guess that is the answer I expected 😄
<FromGitter>
<hmans> I'm going to https://rubyunconf.eu/ this weekend and thinking about doing a talk on Crystal
<FromGitter>
<hmans> But I sort of hate myself for that, because most talks in most Ruby meetups/conferences over here nowadays are about stuff that is not actually Ruby.
<FromGitter>
<sdogruyol> awesome @hmans
<FromGitter>
<sdogruyol> do you want to have a pair review of your talk maybe?
<FromGitter>
<sdogruyol> I could help with that
<FromGitter>
<hugoabonizio> @hmans it's true! but the ruby community was never scared of trying new technology
shalmezad has joined #crystal-lang
<FromGitter>
<straight-shoota> and because of the huge similarity but still different concepts, you get a new perspective on Ruby.
<FromGitter>
<straight-shoota> knowing how things work in Crystal helps getting better at Ruby
<FromGitter>
<straight-shoota> and vice versa
<z64>
+1 ^
<FromGitter>
<yxhuvud> Yeah especially the type checks on nilability.
<FromGitter>
<j8r> Crystal is a bit like a superset of Ruby - except there isn't really backward compatibility with Ruby
<FromGitter>
<hmans> @sdogruyol I have not prepared anything yet, and that may be the problem overall -- it's a very last minute thing, and I'm busy with a project... so I don't know if it'll happen.
<FromGitter>
<hmans> I would probably mostly talk about a side project I'm doing with Crystal, my reasons for using Crystal for it, etc.
<FromGitter>
<sdogruyol> @hmans I see, I think that's also OK
<FromGitter>
<j8r> @hmans what is the project :-) ?
<FromGitter>
<hmans> It's not terribly exciting at this point, just a very fast dynamically served blog
<FromGitter>
<hmans> The intent is to do some Indieweb things. Mmmm. Indieweb things.
<FromGitter>
<hmans> My talk, if I do one, would be roughly about how we're achieving static site-level performance while still rendering things dynamically on the server (off a 64 MB VM), thanks to the magic combination of Crystal and SQLite
shalmezad has quit [Ping timeout: 276 seconds]
<FromGitter>
<j8r> How dynamic is it? Is there an API for dynamic stuff, or all the page is re-rendered for each request à la PHP?
shalmezad has joined #crystal-lang
<FromGitter>
<hmans> This may sound a bit weird, but there are reasons why I'm doing it: it has both. The user-facing blog at / is completely server-rendered. But there's also an /api/ that powers a Vue app (at /app/) that you use for interacting with your site.
<FromGitter>
<hmans> But the stuff that you can see at / (without logging in at /app) is 100% purely server-side. I'm fetching stuff from SQlite, rendering it through Slang. Routing is done by my own little nanoframework.
<FromGitter>
<hmans> Crappy's take on routing request is to basically just tackle it imperatively (instead of decoupling routing and request processing like most routing frameworks do.)
<FromGitter>
<j8r> If I'm correct, SSR (server side rendering) in e.g. React/Vue is done once buy the server, an rendered as a static HTML?
<FromGitter>
<hmans> I don't do JS SSR
<FromGitter>
<hmans> The server-side rendering is pure Crystal.
<FromGitter>
<j8r> But you aren't afraid to have perf penality (even if Crystal is blasing fast)?
<FromGitter>
<hmans> @j8r Individual pages render in under 1ms. I'm afraid of nothing
<FromGitter>
<j8r> Haha ok
<FromGitter>
<hmans> With network round trip, I'm looking at around 35ms to fetch a complete page off the server.
<FromGitter>
<j8r> Maybe I say this because configuring caches like Varnish & co for PHP/Java etc is a nightmare
<FromGitter>
<hmans> Server-side rendering gives me machine readability, though, which is ultra-crucial on the web (especially when engaging in IndieWeb protocols.)
<FromGitter>
<hmans> The instance on cranky.hmans.io can currently serve almost 1400req/s off a 1 core, 64 MB (!) VM
<FromGitter>
<j8r> Yep, but how about scaling - is there an API?
<FromGitter>
<hmans> I'm happy to couple it with an nginx service to do some load balancing, reverse proxying, the likes... but no need so far
<FromGitter>
<hmans> I'm not sure if I understand your question.
<FromGitter>
<j8r> You can have one Vue.js front app with multiple back-ends
<FromGitter>
<hmans> Yes, crankypants has a REST API. I'm just confused how that ties into scaling?
<FromGitter>
<j8r> nvm that's when we separate front/back (I've thinked so becasue you talked about Vue.js)
<FromGitter>
<j8r> That's also useful to separate front/back for: creating a application in Android/iOS, and when we want to refactor the back code
<FromGitter>
<j8r> but I agree: it's simpler to write all in server
<FromGitter>
<j8r> like PHP do
<FromGitter>
<j8r> micro services bring advantages but adds complexity :-/
<FromGitter>
<hmans> Yeah, as mentioned before... the way you (as the site owner) interact with the app is through a Vue app that talks to a JSON API. It's all ready to be used from remote clients.
<FromGitter>
<hmans> / serves a public-facing blog, /api a JSON API, and /app a Vue app that consumes the API.
<FromGitter>
<j8r> why hybrid? Why not all server rendered, or all statically rendered?
<FromGitter>
<j8r> just curious :-)
<FromGitter>
<gdotdesign> server rendered is much better for SEO
<FromGitter>
<gdotdesign> for the admin interface it doesn't matter much
<FromGitter>
<girng> does this effect crystal's development in any way?
<FromGitter>
<hmans> Doing JS SSR would not allow me to run on a 64 MB VM.
<FromGitter>
<j8r> and what about pre rendering?
<FromGitter>
<hmans> (There is a specific reason why I'm doing this, and I'm looking forward *very much* to blogging more about what I'm doing and why)
<FromGitter>
<girng> @jenz yeah. the richtextlabel some reason doesn't parse the blank spaces correctly. it would look better if it did. it would just like from a console
<Jenz>
Sounds fixable though, girng
* Jenz
:eyes:
<Jenz>
Though I have no idea what richtextlabel is (in this case)
<FromGitter>
<girng> @jenz, sorry meant RichTextLabel node from Godot engine. it lets you use bbCode stuff as text in a container. ⏎ ⏎ But yeah, this is how it's supposed tolook like (https://i.gyazo.com/41e39b620af77627f5e57721beef19ab.png), but for some reason when parsing it in the RTL container it doesn't save the spaces correctly
<FromGitter>
<girng> kind of make top cmd look ugly and hard to read
<Jenz>
Right, you're working on some kind of web-game written in crystal right?
<FromGitter>
<girng> well, it's in the godot engine but can be exported to the web. but mostly working on back-end server stuff for it
<FromGitter>
<j8r> you render in html, right?ù
<FromGitter>
<girng> yeah it could. but im targeting towards desktop
<FromGitter>
<girng> i think it exports to webassembly
<FromGitter>
<girng> it also exports natively to linux
<FromGitter>
<girng> which is a huge PLUS
<FromGitter>
<girng> because linux devs love true linux games
That_Guy_Anon has quit [Remote host closed the connection]
havenwood has left #crystal-lang ["Textual IRC Client: www.textualapp.com"]
<RX14>
I think you should use LibC directly
<RX14>
that kind of info is completely platform specific
<FromGitter>
<j8r> It isn't better to have it in the stdlib, like Go does?
<RX14>
it's barely in go's stdlib
<FromGitter>
<j8r> that's strange to have `LibC::Stat` and not `LibC::Statfs`
<FromGitter>
<j8r> both are really platform specific
<RX14>
but we only have libc::stat because it's used in the stdlib for File::Info
<FromGitter>
<j8r> Maybe we can create a sort of `File::FsInfo`?
<FromGitter>
<j8r> It's really useful to know the disk space, I've already done the bindings
<FromGitter>
<j8r> I will send a PR and will see what will happen
<FromGitter>
<masukomi> question about fibers and channels. doc's don't really make this clear. I want to spawn a bunch of things and then wait for them all to finish. I don't want to care how many there are or what order they finish in. What's the right approach here?
<FromGitter>
<j8r> just spawn fibers so
<FromGitter>
<j8r> channels are used to communicate, to send back informations
<FromGitter>
<j8r> *messages
<FromGitter>
<masukomi> so just have a bunch of spawn..do's (or put them in a loop) and then Fiber.yield and after the Fiber.yield everything has finished?
<FromGitter>
<masukomi> @oprypin that snippet makes it look like i have to have a count of how many things {{ jobs.size }}.times { %channel.receive }
<FromGitter>
<masukomi> looking at your thing @j8r
<oprypin>
nothing to look at really
<oprypin>
masukomi, well, don't you know how many things?
<oprypin>
that's not even possible
<FromGitter>
<masukomi> i do but it seems a somewhat silly requirement. i figured there must be some way to just say... hey lemme know when all the things you're managing are done
<oprypin>
masukomi, what if you have a lib that spawns something you're unaware of
<oprypin>
will you also wait for all its tasks? which may be infinite?
<oprypin>
in fact, stdlib probably has infinite tasks as it is
<FromGitter>
<masukomi> there's no way to know my fibers vs your fibers ?
<FromGitter>
<girng> are there any benchmarks showing how many messages per second in a fiber TCP socket?
<oprypin>
masukomi, your fibers are the ones you spawned ;)
<FromGitter>
<girng> btw, what happens when that fiber can't handle those messages per second (are too high). what happens to the fiber, does it start to block the entire program, or does that fiber just start getting slow?
<FromGitter>
<drujensen> anyway to get a list of fibers and filter by name?
<FromGitter>
<masukomi> i was starting to go down that road of exploration but don't see what the point is because i don't see how to tie spawn to a particular fiber
<FromGitter>
<drujensen> aah
<FromGitter>
<masukomi> and oprypin says yield doesn't make it wait for it to finish so even if i could i don't see how i could know that it was done.
<FromGitter>
<masukomi> i really appreciate the help folks. i feel like i must be missing something obvious
<oprypin>
i mean, you're missing the link that i posted
<oprypin>
you tie channels, not fibers
<FromGitter>
<masukomi> like "obviously there's a way to spawn a bunch of stuff that doesn't need to communicate to each other and then wait for it to finish" yes it CAN be done with channels (as in your link oprypin but that brings in overhead i don't need.
<FromGitter>
<masukomi> sure it's minimal and it doesn't really matter in the long run but this really feels like it is something that *should* be there and we're just not seeing it for some reason
<FromGitter>
<hmans> ie., have your spawned fibers report back to a channel
<FromGitter>
<masukomi> i didn't see any example in there that allowed you to wait and didn't require you to keep track of how many things were being spawned
<FromGitter>
<hmans> Oh, I see
<FromGitter>
<masukomi> i get how to do it with channels, but i don't need cross communication and it *feels* like a pretty common use case
<FromGitter>
<masukomi> sorry. not trying to be obstinate
<oprypin>
masukomi, if you dont want to keep track of how many things, you can also make N channels instead of 1 and wait for each.......
<oprypin>
you may have a valid complaint that there isnt a standard wrapper to do this, but that's what it would do - count thing
<oprypin>
s
<FromGitter>
<masukomi> so in that case i'd do a bunch of channel.new's and then... loop over them until there were none left that returned a non truthy `receive?` ?
<FromGitter>
<hmans> @masukomi Consider that this isn't really a Crystal specific problem. Go has something called WaitGroup to wrap around it
<FromGitter>
<masukomi> i *think* i have enough info to move forwards. am i right about the `receive?` idea?
<FromGitter>
<hmans> Assuming you have a module, class or other piece of code that is considered to be in control of spawning these fibers, it would need to do tracking of some sort. Doesn't need to be a channel. I suppose the units of work could also just decrement a number that was incremented when they were spawned, and the controlling fiber waits for the number to go back down to 0.
<FromGitter>
<masukomi> mmm
<FromGitter>
<hmans> And checking for non-blocking `receive?` might work, yeah, but it feels more complex than necessary
<FromGitter>
<masukomi> *nods* cool. thank you all. if i come up with some good wrapper for this i'll make a PR
<FromGitter>
<hmans> \o/
<FromGitter>
<hmans> From Go's WaitGroup: "A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished."
<FromGitter>
<hmans> You can see there's some really basic stuff going on behind the scenes there.
<FromGitter>
<j8r> How can I use `LibC.stat` directly? I tried some combinations of `LibC.stat("/home", result : LibC::Stat)` but still stuck :-/
<FromGitter>
<j8r> also tried `uninitialized` and `Pointer.new`
<FromGitter>
<girng> if i use a custom dns address server, no sites will load.
<FromGitter>
<girng> i tried cloudflare, and j8r's dns.watch
<FromGitter>
<girng> in any event im done wasting my time on this premature optmization bullshit
<FromGitter>
<j8r> Don't know how in Windows
<FromGitter>
<girng> my sites load just fine
<FromGitter>
<j8r> Changing DNS is primilarly for privacy
<FromGitter>
<j8r> not really perf
<FromGitter>
<hmans> I'm adding `hardware` to crankypants...
<FromGitter>
<hmans> @j8r memory.percent seems to always claim a usage of 20% -- work in progress?
<FromGitter>
<hmans> (memory.used is 836064, which seems realistic)
<FromGitter>
<bararchy> @hmans what distro?
<FromGitter>
<hmans> @bararchy This is currently inside a Docker VM running on a Mac. The Container is using the Crystal image. I'm assuming the 20% is Docker related?
<FromGitter>
<hmans> Let me run it outside of Docker...
<FromGitter>
<hmans> (Will it even work on something that's not Linux?)
<FromGitter>
<hmans> (Well, I just found out :b)
rohitpaulk has quit [Ping timeout: 264 seconds]
<FromGitter>
<j8r> For now it only works in Linux. Maybe some things in BSD variants, but I doubt...
<FromGitter>
<j8r> Use another tool to check the CPU usage if it match or not, like `top`
<FromGitter>
<j8r> sorry you said memory, check with `free -g`
<FromGitter>
<hmans> I will dig deeper tomorrow. Bed time for me.
<FromGitter>
<girng> gn
<FromGitter>
<hmans> Talk to you guys tomorrow o7
<FromGitter>
<j8r> see you!
duane has quit [Ping timeout: 240 seconds]
<crystal-gh>
[crystal] j8r opened pull request #6056: Add bindings for LibC::Statfs (master...statfs) https://git.io/vpaqf
duane has joined #crystal-lang
sz0 has joined #crystal-lang
<FromGitter>
<girng> is opyrin on
<FromGitter>
<girng> guess not. anyway, anyone can help
<FromGitter>
<girng> damnit, the ips are supposed to be different. They are different servers
<FromGitter>
<fridgerator> communication is via websockets?
<FromGitter>
<girng> via tcp stream
<FromGitter>
<girng> they are connected though. i make a connection to them through tcp to let the master server know
<FromGitter>
<fridgerator> and message are sent and retrieved?
<FromGitter>
<girng> yeah. but only for important stuff. like for example if someone finds and items and loots it
<FromGitter>
<girng> i need it to be saved on the master items database
<FromGitter>
<fridgerator> well I can only speak to how websocket servers usually work, all messages are posted to something like Redis
<FromGitter>
<girng> do i send a message to notify the master server to run the db.query. or do i just connect to the database from the game instance server
<FromGitter>
<fridgerator> each instance of the server posts all messages to Redis, they also each listen to Redis for new messages
<FromGitter>
<girng> remotely db connection, and then do it. or do i send a message internally tcp to master server user_id, itemid that they looted, then update the db
<FromGitter>
<fridgerator> so a Redis service is kind of used like a "master"
<FromGitter>
<girng> yeah i did that with nodejs
<FromGitter>
<girng> redis pub sub stuff
<FromGitter>
<fridgerator> yeah
<FromGitter>
<girng> so i guess the game instance server will notify the master. then the master runs the database query. that's how i would do it with a redis pubsub. but i mean, i could open up my mysql db connection remotely. and have the game instance server connect to it. then just call the database query on that game instance server. im not sure
<FromGitter>
<girng> there's so many freaking ways to do it
duane has quit [Ping timeout: 260 seconds]
<FromGitter>
<fridgerator> Well, the database is going to be a bottleneck with lots of users
<FromGitter>
<fridgerator> I wouldn't write / read from a database on every action
<FromGitter>
<girng> oh yea for sure. i mean like if a player loots an item though
<FromGitter>
<girng> it needs to be saved to their inventory instantly
<FromGitter>
<girng> i just don't know if that save query should be just called on the game instance server, or on the master server.
<FromGitter>
<girng> if on game instance server, it will need to create a connection to the main database. im not sure if that's safe
<FromGitter>
<girng> main mysql port will be open
<FromGitter>
<girng> 3306
hightower2 has joined #crystal-lang
<hightower2>
Hey, I have kind of an abstract question :) I know I can make an abstract class or define things within a module as abstract, But is there a way to check that I am only invoking the methods on an object which are defined in that abstract interface?
Nathanaelle has quit [Ping timeout: 240 seconds]
<FromGitter>
<j8r> not sure to understan @hightower2
<FromGitter>
<j8r> You define abstracts, and ther create a class that inherit of the abstracted class