Re: [capnproto] Schema Mismatch Between Client and Server

2023-02-14 Thread Matt Stern
Awesome, thanks so much!

On Tue, Feb 14, 2023, 8:01 PM Kenton Varda  wrote:

> Hi Matt,
>
> Your idea would work initially, but if an @3 field were ever added, it
> could end up incompatible.
>
> Instead, assuming `Internal` is a struct type, you can instead declare
> `internal` to have type `AnyPointer`:
>
> struct Event {
>   union {
> foo @0 : Foo;
> bar @1 : Bar;
> internal @2: AnyPointer;
>   }
> }
>
> Since `Internal` is a struct, a field of type `Internal` is represented as
> a pointer. Since `AnyPointer` is also a pointer, it'll produce the same
> layout.
>
> At the risk of over-engineering, another option would be to use generics:
>
> struct Event(InternalType) {
>   union {
> foo @0 : Foo;
> bar @1 : Bar;
> internal @2: InternalType;
>   }
> }
>
> This way, you and your consumers can actually use exactly the same
> definition of `Event`. Your consumers would use `Event<>` (which is
> equivalent to `Event`). In your internal code with
> knowledge of the internal type, you'd use `Event`.
>
> -Kenton
>
> On Tue, Feb 14, 2023 at 1:21 PM Matt Stern  wrote:
>
>> Hi Capnp folks,
>>
>> I have a producer that writes events to a queue. The schema looks like:
>>
>> struct Event {
>>   union {
>> foo @0 : Foo;
>> bar @1 : Bar;
>> internal @2 : Internal;
>>   }
>> }
>>
>> There are downstream consumers of this queue that are meant to ignore the
>> "internal" field -- in fact, we don't even provide the Internal struct
>> definition to them.
>>
>> The downstream consumers have had a lot of log spam lately because they
>> use this stripped down schema to generate code:
>>
>> struct Event {
>>   union {
>> foo @0 : Foo;
>> bar @1 : Bar;
>>   }
>> }
>>
>> and then handle the union with a switch/case like so:
>>
>> switch (reader.which()) {
>>   case FOO: return handle(reader.getFoo());
>>   case BAR: return handle(reader.getBar());
>>   default: return logError("A new message type exists that we don't know
>> about!");
>> }
>>
>> The default case in the switch makes sense -- if a new message type
>> appears from the producer, we should surface that in some way so the
>> consumers know to update their schemas and handle the new message. However,
>> we don't want to trigger this case for the known Internal type, which
>> consumers don't need to handle.
>>
>> I am thinking of giving the consumers a new schema that looks like:
>>
>> struct Event {
>>   union {
>> foo @0 : Foo;
>> bar @1 : Bar;
>> internal @2: Void;
>>   }
>> }
>>
>> so they can explicitly ignore the internal messages but still log errors
>> for other new messages that may appear.
>>
>> My question boils down to: Is it safe for the producer to assign one type
>> (struct Internal) to field 2 but the consumer to assign another type
>> (Void)? Or would this cause issues?
>>
>> Thanks!
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Cap'n Proto" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to capnproto+unsubscr...@googlegroups.com.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/capnproto/f94fe404-b080-4654-bfc6-c578c411cf55n%40googlegroups.com
>> 
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/CAL717_Rt-%2BRygcn_ewFCLaqhLYQ3MVuVsXbRP1M7jZmsHOkwJw%40mail.gmail.com.


Re: [capnproto] Schema Mismatch Between Client and Server

2023-02-14 Thread 'Kenton Varda' via Cap'n Proto
Hi Matt,

Your idea would work initially, but if an @3 field were ever added, it
could end up incompatible.

Instead, assuming `Internal` is a struct type, you can instead declare
`internal` to have type `AnyPointer`:

struct Event {
  union {
foo @0 : Foo;
bar @1 : Bar;
internal @2: AnyPointer;
  }
}

Since `Internal` is a struct, a field of type `Internal` is represented as
a pointer. Since `AnyPointer` is also a pointer, it'll produce the same
layout.

At the risk of over-engineering, another option would be to use generics:

struct Event(InternalType) {
  union {
foo @0 : Foo;
bar @1 : Bar;
internal @2: InternalType;
  }
}

This way, you and your consumers can actually use exactly the same
definition of `Event`. Your consumers would use `Event<>` (which is
equivalent to `Event`). In your internal code with
knowledge of the internal type, you'd use `Event`.

-Kenton

On Tue, Feb 14, 2023 at 1:21 PM Matt Stern  wrote:

> Hi Capnp folks,
>
> I have a producer that writes events to a queue. The schema looks like:
>
> struct Event {
>   union {
> foo @0 : Foo;
> bar @1 : Bar;
> internal @2 : Internal;
>   }
> }
>
> There are downstream consumers of this queue that are meant to ignore the
> "internal" field -- in fact, we don't even provide the Internal struct
> definition to them.
>
> The downstream consumers have had a lot of log spam lately because they
> use this stripped down schema to generate code:
>
> struct Event {
>   union {
> foo @0 : Foo;
> bar @1 : Bar;
>   }
> }
>
> and then handle the union with a switch/case like so:
>
> switch (reader.which()) {
>   case FOO: return handle(reader.getFoo());
>   case BAR: return handle(reader.getBar());
>   default: return logError("A new message type exists that we don't know
> about!");
> }
>
> The default case in the switch makes sense -- if a new message type
> appears from the producer, we should surface that in some way so the
> consumers know to update their schemas and handle the new message. However,
> we don't want to trigger this case for the known Internal type, which
> consumers don't need to handle.
>
> I am thinking of giving the consumers a new schema that looks like:
>
> struct Event {
>   union {
> foo @0 : Foo;
> bar @1 : Bar;
> internal @2: Void;
>   }
> }
>
> so they can explicitly ignore the internal messages but still log errors
> for other new messages that may appear.
>
> My question boils down to: Is it safe for the producer to assign one type
> (struct Internal) to field 2 but the consumer to assign another type
> (Void)? Or would this cause issues?
>
> Thanks!
>
> --
> You received this message because you are subscribed to the Google Groups
> "Cap'n Proto" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to capnproto+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/capnproto/f94fe404-b080-4654-bfc6-c578c411cf55n%40googlegroups.com
> 
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/CAJouXQ%3DDYGk7NFjajnw4j8J%2BZM%3Dto-_ur92zL%2BqmovodO7oQug%40mail.gmail.com.


[capnproto] Schema Mismatch Between Client and Server

2023-02-14 Thread Matt Stern
Hi Capnp folks,

I have a producer that writes events to a queue. The schema looks like:

struct Event {
  union {
foo @0 : Foo;
bar @1 : Bar;
internal @2 : Internal;
  }
}

There are downstream consumers of this queue that are meant to ignore the 
"internal" field -- in fact, we don't even provide the Internal struct 
definition to them.

The downstream consumers have had a lot of log spam lately because they use 
this stripped down schema to generate code:

struct Event {
  union {
foo @0 : Foo;
bar @1 : Bar;
  }
}

and then handle the union with a switch/case like so:

switch (reader.which()) {
  case FOO: return handle(reader.getFoo());
  case BAR: return handle(reader.getBar());
  default: return logError("A new message type exists that we don't know 
about!");
}

The default case in the switch makes sense -- if a new message type appears 
from the producer, we should surface that in some way so the consumers know 
to update their schemas and handle the new message. However, we don't want 
to trigger this case for the known Internal type, which consumers don't 
need to handle.

I am thinking of giving the consumers a new schema that looks like:

struct Event {
  union {
foo @0 : Foo;
bar @1 : Bar;
internal @2: Void;
  }
}

so they can explicitly ignore the internal messages but still log errors 
for other new messages that may appear.

My question boils down to: Is it safe for the producer to assign one type 
(struct Internal) to field 2 but the consumer to assign another type 
(Void)? Or would this cause issues?

Thanks!

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/f94fe404-b080-4654-bfc6-c578c411cf55n%40googlegroups.com.