<dwrensha>
(in Rust you need to use a macro to do this, whereas in C++ you'd just use templating)
<dwrensha>
interface_list::Reader::borrow should probably exist for consistency. Though it looks like I haven't actually implemented it for all of the other list types, so meh.
<dwrensha>
geofft: I think that any nontrivial tests for interface_list would need to go in capnp-rpc-rust
<dwrensha>
we should add a /tests directory as we have in capnpc-rust
<dwrensha>
hm... though maybe in capnp-rpc there is less of a bootstrapping problem, so that /tests doesn't need to be in its own crate (In capnpc-rust, /tests is its own crate because otherwise how would it handle code generation?)
gopar has joined #sandstorm
jadewang has quit [Remote host closed the connection]
wat has quit [Quit: a]
wat has joined #sandstorm
jadewang has joined #sandstorm
jadewang has quit [Remote host closed the connection]
decipherstatic_ has quit [Remote host closed the connection]
<paulproteus>
It's like CSS selectors for processes.
larjona has quit [Quit: Konversation terminated!]
larjona has joined #sandstorm
<warren>
paulproteus: is now a better time?
<paulproteus>
Sure.
<geofft>
ugh, is the way to convert a struct that impls an interface to a capability ToClient(thing).from_server(None::<LocalClient>)?
<geofft>
(in capnproto-rust)
<geofft>
does anyone actually use the FromServer trait? I feel like this could just be a straightup function
<dwrensha>
geofft: yeah, that ToClient thing is really ugly
<dwrensha>
geofft: I'll need to remind myself of the purpose of FromServer...
<geofft>
git grepping, it only seems to be used in the examples
<dwrensha>
geofft: I'm not remembering any good reason why FromServer needs to be a trait
<dwrensha>
geofft: Also, looks like we can do away with the the `hook: Option<T>` argument and make `T` a type parameter
<dwrensha>
... and change the signature of ServerHook::new_client() so that it doesn't take an "unused optional self"
<dwrensha>
and then in FromServer::from_server, call `T::new_client()`
<geofft>
hm, I'm stuck somewhere more basic. ToClient seems to want to take ownership?
<dwrensha>
Right. If you have a Server and want to call it from the RPC system, you have to hand it off to the RPC system.
<dwrensha>
... and you get back a Client that you can call.
<geofft>
ok, I feel like I did something wrong in my design then.
<geofft>
on the capnp side, I have a bootstrap interface that can give me a List(Workspace), and each Workspace can give me a List(Command)
<geofft>
I _thought_ I want to implement this with a struct Bootstrap {workspaces: Vec<Workspace>), struct Workspace {commands: Vec<Command>}
<geofft>
and impl bootstrap::Server for Bootstrap, impl workspace::Server for Workspace
<geofft>
should I be using something other than an owning vec? like should I hold an owning vec of Clients or something?
<geofft>
(or should I be backing this by real capnp structures? at the moment I'm looping over the vec to populate the return of getWorkspaces() and getCommands(), which feels maybe wrong)
<dwrensha>
there are a number of ways you could get that to work. I'm not sure which is best.
<dwrensha>
You certainly won't be able to keep owning the WorkspaceImpls after you've returned them.
<dwrensha>
You could hold onto something like Vec<Rc<RefCell<WorkspaceImpl>>>, and implement Workspace::Server fo Rc<RefCell<WorkspaceImpl>>
<dwrensha>
but that's kind of ugly
<dwrensha>
the RPC system does its own refcounting, so it would be sad if you had to do your own refcounting too
<geofft>
yeah, thinking a bit more, I think the reason I'm confused is that the calculator example has no nontrivial data (afaict)
<geofft>
just numbers and static data like operators
<dwrensha>
it's all interfaces!
<dwrensha>
objects the whole way down!
<geofft>
so if I want a Command that holds something like a std::Process::Child, which can't be directly represented in a capnp message, can't be copied, etc.
<dwrensha>
it would be nice if we had another more straightfoward RPC example
<geofft>
either I want a struct Command { child: Child } with impl command::Server for Command
<geofft>
or a struct Command { child: Child, rpcserver: CommandImpl }
<geofft>
and I think ownership in Rust gets super hairy for the second approach
<geofft>
'cause rpcserver wants a reference to child so it can do stuff on child
<dwrensha>
hm... it occurs to me that my Rc suggestion doesn't work because the Server needs to be 'static in order to pass it to the RPC system
<geofft>
I'd be happy to hand the first type of struct Command off to the RPC system, if I have a way to get it back so I can use the child
<geofft>
but it feels like getting a command::Client doesn't really help me?
<dwrensha>
... or, rather, 'static + Send
<maurer>
geofft: I could be mistaken, but could you not just wrap a std::Process::Child in a capnproto interface?
<maurer>
geofft: And then send the capability pointer to the other thread, which would be sendable, because the child never actually goes anywhere?
<maurer>
geofft: Like, if the problem is that you can't ship/serialize std::Process::Child around, it seems like a prime candidate for wrapping in an interface and just talking to over rpc
<geofft>
I'm trying to figure out _how_ to wrap it
<maurer>
Oh, sorry, guess I misread
* maurer
reads up
<geofft>
the Child itself stays entirely on the server, the client only interacts with it over capnp-rpc ("write to stdin" / "call this method on this interface when it writes to stdout")
<geofft>
I might be misunderstanding you because I am pretty confused right now :)
<maurer>
16:28 < geofft> so if I want a Command that holds something like a std::Process::Child, which can't be directly represented in a capnp message, can't be copied, etc.
<maurer>
was the thing I was trying to respond to
<geofft>
right. I'm trying to figure out how to define a structure that contains a Child and also can be interacted with over capnproto-rpc
<maurer>
a way to represent the Child in your Command message would be to make a parameter to your Command message be a capability corresponding to the child
<geofft>
(which feels like it should be an obvious thing, yes, but I'm not seeing an example)
<maurer>
OK, now I don't understand what you're trying to do, or where your issues are
<maurer>
Do you have code up somewhere?
<maurer>
A .capnp file maybe?
<geofft>
I can toss code up somewhere if that'd help, sure, but lemme see if I can try explaining better?
<geofft>
or ... do you want me to impl something::Server for std::Process::Child _itself_? that might work
<maurer>
That is what I was suggesting
<maurer>
e.g. your interface would probably (assuming i'm thinking of it right) look something like
<maurer>
bootstrap->getWorkspaces() producing a list of workspaces
<dwrensha>
geofft: the model right now for capnp-rpc-rust is "each object lives in its own thread". So if your Command::Server needs access to a Child and you need access to that Child elsewhere, you're going to need to synchronize
<maurer>
workspace->someCommands(), some of which produce threads
<geofft>
but the calculator example involves creating a new SomethingImpl object at every site that you're returning a capability
<geofft>
and I didn't want to do that, I wanted to hand the RPC system a reference to an existing object that I already own
<geofft>
because I knew in the future I wouldn't want to create a new CommandImpl object with a new Child, I want to track the existing Child
<geofft>
but maybe what I should be doing is creating a new CommandImpl object with a reference to an existing Child?
<geofft>
or creating a new CommandImpl object with an RPC reference to an RPC-system-owned Child, which is the thing maurer suggested
<dwrensha>
Yeah, making everything a Cap'n Proto object sounds cleanest to me.
<dwrensha>
or, at least, it sounds to me like your only hope of avoiding Arc and Mutex/RwLock
<geofft>
does this change notably with a GJ-based capnproto-rust? long-term, I don't really want two threads per child process :(
<geofft>
short-term, whatever
<dwrensha>
Yeah, I think in a GJ would you would have a Rc<RefCell<Child>> that you would share with the CommandImpl
<geofft>
if you're curious, https://paste.debian.net/284977/ is the .capnp file that I'm trying to get implemented to convince myself this will work
<geofft>
it is way incomplete
<dwrensha>
*GJ world*
<paulproteus>
Oh hey geofft this is a cool capnp file.
<geofft>
yeah I suppose GJ will involve enough changes that I shouldn't optimize for "am I gonna have to rewrite everything"
<geofft>
i,i "plan to throw one away"
<dwrensha>
In C++ you might just share references to the Child without reference counting. Less overhead, but more dangerous.
<geofft>
I keep thinking I should write this in C++ just because the capnp infrastructure is way more mature, and also I don't have to do infinite bindings to signals and subprocesses and termios
<geofft>
butbut Rust
<geofft>
ok, I have an idea of where to go from here, thanks dwrensha and maurer :)
<dwrensha>
geofft: you are providing me with valuable feedback :)
<geofft>
once I get somewhere, I'm happy to turn this into an example if you want capnp-rpc-rust to have something with more complicated ownership than the calculator thing
<dwrensha>
geofft: that could be cool :)
<paulproteus>
Agreed.
<geofft>
hm, I suppose I want a separate .capnp file for the server-internal interface to Child?
<geofft>
although now I'm second guessing myself about whether any of that is actually internal and how capabilities vs. public/private works.
<paulproteus>
I see, modern.ie is 32-bit. Hmm.
<larjona>
Hi everybody. I'm having some troubles to understand sandstorm.io. I have deployed my instance in my home server. I have installed gitweb,created two repos, and the URL for cloning is changing each time I click in "home" in the gitweb repo. Whatever. I didn't understand very well gitweb, so I uninstalled the app. But my repos are still there. Shouldn't them be destroyed when I uninstall the app?
<paulproteus>
larjona: Installing/uninstalling is mostly about the ability to create _new_ instances of the app (aka new repositories in this case).
<paulproteus>
The current design is that uninstalling an app doesn't break your ability to use instances you've already created.
<paulproteus>
Maybe that's confusing, and the "Uninstall" process should say something to that effect, like, "App uninstalled. OK to retain existing app instances, or Delete All GitWeb Data?"
<dwrensha>
larjona: the "different URL each time" thing is the expected behavior
<dwrensha>
larjona: we generate a new token each time, but they go away quickly unless you actually connect with a git client
<larjona>
but if somebody git clones with that url, will it be persistent? I mean, if two weeks later she wants to update her clone with git pul
<larjona>
pull*
<kentonv>
larjona: yes
<kentonv>
you can keep pushing and pulling without entering a new URL
<larjona>
And the password?
<kentonv>
the password will continue to work
<kentonv>
the idea is that by handing out different passwords, you could, in theory, separately revoke them. We haven't built the UI for that yet, though.
<larjona>
I understand
<kentonv>
larjona: ideally you should use the git credentials helper to save the password, so you don't have to type it in repeatedly... we need better instructions for that.
<dwrensha>
also, we should show some kind of visual indication for when you successfully connect a git client
<larjona>
Thanks.
<maurer>
geofft: if you want to see a "real" project using capnp-rpc-rust, you can look at maurer/holmes
<maurer>
geofft: Unfortunately I don't quite have approval to release some of the daemons that talk to it yet, but you can get an idea of how I'm using it
<dwrensha>
i,i release the demons
<geofft>
Krak'n Proto
<dwrensha>
paging aldeka ^
<dwrensha>
I would wear that T -shirt
<aldeka>
soggies may rule
<aldeka>
That sounds like a hy capnp implementation.
bb010g has quit [Quit: Connection closed for inactivity]
<geofft>
ohhhh now I understand why everything has a +Send bound :(
<geofft>
cause it's literally all on different threads
<maurer>
Yes.
<maurer>
If gj does what I think it's going to do, the send bound might be removable by connecting the object to the event loop in the current thread
<maurer>
but I am not the designer, so that's for dwrensha to say
<dwrensha>
Yes, in GJ your Servers would not need to be Send
bb010g has joined #sandstorm
<geofft>
maurer: this is helpful, thanks!
<geofft>
I'm looking at HolmesImpl::new_func 'cause that seems to be the one interesting use of interfaces
<maurer>
Yeah, that's intended to allow external programs to register themselves with the logic engine
<maurer>
so they can be like "Hey, I implement a function called foo, let users call it in rules"
<maurer>
the whole thing is not as capabilities oriented as it could be - right now the API enforces a spoke architecture
<maurer>
If I were to do it "right", I'd stop using string names in the code representation of rules and use capabilities directly
<maurer>
but I've got other things to work on
<geofft>
... wait up, why is Box<ClientHook+Send> a unique-ownership type?
<dwrensha>
geofft: there's a copy() method, I think
<dwrensha>
which increases the refcount
<geofft>
oh so there is
<paulproteus>
I love writing tests in installer-tests/ !
larjona has quit [Quit: Konversation terminated!]
<dwrensha>
I see that Jenkins failed again with " expected target->getBrand() == this; 'Disembargo' of type 'senderLoopback' sent to an object that does not point back to the sender. "
<dwrensha>
I was just now able to get that to happen again on my machine
<dwrensha>
I'll see if I can get anywhere on isolating it...