Component polymorphism support feature & prototype

Hello,
I'd like to introduce my work on prototype feature, that adds component polymorphism support. Such thing might seem a little controversial, so I will immediately mention two things:

Despite not being a part of pure ECS concept, such feature can be very useful in many real world cases
It is enabled only for certain component types at compile time, so it will not affect performance of non-polymorphic components in any way (pay only for what you use)

I already have working prototype in the experimental branch of my fork. Of course it requires some review and improvements, and some parts may not be made in a nicest way possible right now, but it is fully functional.
Here is a basic example:
struct Ticking : public entt::polymorphic {
    virtual void tick(const entt::entity) = 0;
};

class Physics : public entt::inherit<Ticking> {
    // ...
    void tick(const entt::entity e) override {
         // ...
    }
};

class AI : public entt::inherit<Ticking> {
    // ...
    void tick(const entt::entity e) override {
         // ...
    }
};

registry.emplace<Physics>(e); // emplace polymorphic component
Ticking& ticking1 = registry.get<Ticking>(e); // will return Physics as Ticking
registry.emplace<AI>(e); // emplace another polymorphic component
Ticking& ticking2 = registry.get<Ticking>(e); // will return any of two components, because they are both inherit from Ticking, which component is returned is not defined

// get iterable to iterate each component, that is inherited from Ticking, order of iteration is not defined
for (Ticking& ticking : registry.view<entt::every<Ticking>>(e).each()) {
    // ...
}

// view can also get every component instead of one
registry.view<entt::every<Ticking>>(e).each([](const entt::entity, entt::every<Ticking> every_ticking) {
    for(Ticking& ticking : every_ticking) // ...
});

// will remove EVERY component, that is inherited from Ticking
registry.remove<Ticking>(e);

You can try it yourself, it is already in the fork, along with some tests. I will appreciate any feedback about how to improve both the concept and the solution, and hope it will make it way into EnTT in the future.
Now lets dive into some details:
Problems, I try to address
Maybe the main problem, this feature solves, is accessing components without knowing their exact type. It is sometimes can be very useful to access component as some interface/base type without knowing what exactly it is (so basically this is what polymorphism is about in general, and this feature is applying this concept to ECS).
In the context of ECS it results in 2 main ideas: we should be able to access component by any of its base types and we also should be able to access all such components, attached to an entity, because there of course can be more than one. Example of this idea is already shown above, we create two component types, that implement Ticking interface and add both of them to an entity, and then we can just iterate all ticking components and do something with them (probably just call tick in this case).
Additionally, to follow "pay only for what you use" rule, such polymorphic components must be treated separately and must not affect performance of other components.
Some specs
The basic idea is simple: component can be accessed not only by its own type, but by any of its parent types. From the example above we can see, that both Physics and AI components inherit from, and so can be accessed as reference to Ticking. Here I tried to come up with a bit more formal set of rules:

We define polymorphic components separately from non-polymorphic, by inheriting from entt::polymorphic or entt::inherit<Parent1, Parent2, ...>. Polymorphic component can inherit only from other polymorphic components to keep them separate from non-polymorphic. With this requirement we can completely separate all logic at the compile time and preserve performance for non-polymorphic components.
When polymorphic component is added to entity, it can then be accessed not only by its own type, but as any of its parent types. This applies both for getting it for one entity and for iterating with a view.
Now for some parent type there can be several components of its child types attached to an entity. So we must be able to:
3.1. Still get one of this components, if we just need one. This operation ideally must be as fast, as getting one non-polymorphic component. Which component will be returned cannot be specified in this case, so we just return any of them.
3.2. Iterate over all components of this type, attached to an entity. Same as with one component, we must be able to use it both with get and with view. To achieve this, we pass entt::every<ParentType> instead of just ParentType to registry.get or registry.view, and get it back. Then we just iterate entt::every<ParentType> to get ParentType&.
3.3. Access with entt::every must work completely similar for one and for several components.
Calling erase and remove must delete all components inherited from given type. This might seem a bit controversial, because in some cases we need to delete component of exactly this type, so maybe in the future separate method should be added to do such things.
Actions insert, get_or_emplace are deleted for polymorphic components right now, and patch is also controversial one, as they deserve separate discussion.
... This list will be expanded as the discussion progresses

Some implementation details
Wrappers (or containers, don't know, which name is better)
Main idea here is to store polymorphic components inside wrappers/containers (polymorphic_component_container<Component>). These wrappers are able to store component value of exactly given type and reference list to other components. They have storage for component value, list of references to other components and 2 bits for flags to store its state.
Wrapper has methods for value construction/destruction, adding/removing references to other components from reference list and for getting reference to one component or entt::every to iterate all of them. When constructing a value, wrapper adds reference to this value into all wrappers for parent component types, when destructing - it will remove all this references. So it requires registry and entity to access those wrappers for parent types.
Polymorphic components reference each other by pointer, so stable pointer is required, in_place_delete is true for all polymorphic types, and empty type optimization is also disabled, because wrappers are never empty.
Changes in basic_storage
Because polymorphic components are stored in wrappers and accessed in a slightly different way, separate basic_storage and iterator implementations are created for them. It changes implementation of get, emplace, erase and remove and also adds hidden methods for polymorphic_component_container like emplace_ref and erase_ref.
I have also added get_as<T> (and similar) methods for all basic_storage implementations and similar as<T> methods for storage iterators. The purpose of those is resolving entt::every (and maybe some other type modifiers in the future). For non-polymorphic storage those methods are completely similar to get/operator*, they actually just call them with an extra static_assert, so no performance overhead here.
And here comes an uglier part: emplace and erase now require registry for polymorphic storage, so right now they are just passed as an additional parameter, that is ignored for non-polymorphic component storages. Again, no performance overhead here, as the registry parameter is just optimized out, but the whole idea of such inverse dependence is pretty nasty. It is another open discussion on how to implement this in a more elegant way.
Changes in basic_view
Here things are simpler: I use get_as<T>/as<T> methods I have created in storage and storage iterators to just forward everything in a right way. Because all of these methods are basically same as get/operator* used before for non-polymorphic types, no overhead is expected for them.
There is also some changes to get unwrap entt::every to get storages for required component, but these are fully resolved at compile time.
Changes in basic_registry
Only changes here are passing registry to emplace/erase/remove and unwrapping entt::every for views.
Dive into polymorphic_component_container implementation
As was said before, polymorphic_component_container aka polymorphic component wrapper can store both component value and reference list. In a very basic implementation it can be done like this (and also thinking of it in this way may help a lot):
template<typename Component>
struct polymorphic_component_container {
    std::optional<Component> value;
    std::vector<Component&> refs;
};

But when I came to thinking about erase implementation the following problem kicked in. When erasing component, we must also erase all components listed in refs (those are child types). When deleting component, it must delete all of its references from parent wrappers, so we must know exact types of components in refs to do it or come up with another way. My idea was to store pointer to 'deleter' function along with component reference, such deleter will be placed when reference is added and called, when it is required to erase component by its reference. So wrapper implementation should look like this:
template<typename Component>
struct polymorphic_component_container {
    struct component_ref {
        Component& ref;
        void* deleter;
    };
    std::optional<Component> value;
    std::vector<component_ref> refs;
};

Now lets move on to real implementation. It does not use std::vector nor std::optional. Instead it has data - buffer for component value or at least one pointer and uintptr_t pointer, which can store pointer to one reference or pointer to list, depending on wrapper state. And to store wrapper state I use a solution with some pointer hacks - I rely on memory alignment, so 2 bits of pointer are always zero and can be used to store the state (it is achieved by aligning entt::inherit by at least 4 bytes). This saves us one memory access when getting reference to the component and also sizeof(pointer) bytes of memory per wrapper, that would be otherwise added by padding. I thought it was worth it, so there is a lot of strange stuff going on inside wrapper, but if you consider this an overkill I of course will rethink it.
Now lets look on the possible storage states: there are 2 bits, 2 flags that are mostly independent of each other, 1st flag - if wrapper has a value, 2nd flag - if wrapper has a reference list. Describing whole implementation here would take forever, I will try to do it separately, so here are some important notes:

There is always a value or a reference stored directly inside the wrapper, so one component reference can be always accessed without any indirection and looking into list. If nothing is stored, wrapper is deleted.
When wrapper has list, it stores all the references, owned by this wrapper, including reference to the value inside this wrapper (if in has one), so iterating the list does not require extra logic.
When wrapper contains only one reference or only value, it does not allocate a list (and also it deallocates a list, if only one reference/value remains)
Lists are allocated via component_ref_list_page_source to optimize many small memory allocations of the same size, required for them. Note: right now template of component_ref_list_page_source depends only on underlying allocator type, but maybe it should instead be instantiated per component type (the page size must be reduced greatly in this case).

I am planning to clean up, and move some of this logic out of the wrapper class to abstract underlying memory layout a bit, right now the solution is messy.
...Implementation details are also to be expanded

Hi, I see that your branch has 10 changed files with 2,170 additions and 112 deletions.
My first suggestion is to provide the reader with a walkthrough of your work and reasoning. Otherwise, it may take a while before getting a feedback.
Another thing that helps to focus on your proposal is to clearly define the goals of this work. Polymorphism support is somewhat vague. A list of use cases and problems you're trying to address would help on the other hand. Otherwise, agani, it may take a while before knowing what this code adds to the whole picture.
That being said, let's start with scratching the surface though. A bunch of questions/doubts after a quick glance:

The fact that both page_size and in_place_delete depend on the polymorphic nature of a type is really odd to me in terms of design. Why is it required at all?
The sparse set doesn't know about the registry class today and and I'd rather stick with this approach.
How does this affect the view perf? I see many changes but I can't easily figure out if they add up for the non-polymorphic case.

I won't go into the details of storage.hpp and component.hpp right away, mainly because they are very huge and with many changes. I'm a little short in time today. 😅
Something that looks odd is the storage specialization for is_polymorphic_component_v<Type>. I don't get why being a polymorphic type should affect the storage type.
As I was reading your proposal, I thought of a much less impactful implementation to support polymorphic types. It would also fit with an upcoming feature, literally entering the same design.
However, I'd like more details about your work and it would be really helpful if you could guide me through it as suggested at the beginning. It might just be enough with a clean up already but I really struggle to grasp all the details from the code alone, sorry.

Thanks for your reply! I will write in details about ideas and implementation and put it in the heading comment for easier access as soon as possible.
And also here is a brief response for your first questions:

Polymorphic components are stored in wrappers inside the storage, and reference each other by pointer, so they must have stable pointer and also prevent empty type optimization. page_size is zero for empty type components, so polymorphic check was added to prevent this for empty, but polymorphic types. in_place_delete is an overkill, because it was duplicated in entt::inherit, I will clean it up.
When polymorphic component is added, it adds its reference into all parent type storages, and when it is removed, it must delete all those references. So the idea that it requires registry to get those storages. Making duplicate emplace/remove methods for storages and sparse sets to pass registry were the fast way to do it, but I admit it is an ugly one and must be refactored. Even when I was writing it I have already decided to discuss it with you, because you will suggest the best way to solve this problem.
I haven't yet tested two versions of the library (with and without my changes) side by side. But the whole idea here was to separate all the logic at compile time, so logic for non-polymorphic components stays completely the same. All alternative methods, that were added, contain additional logic only for polymorphic components types, for non-polymorphic they just have additional unused parameters or wrap a call to another function. It should all be optimized out completely, when it is inlined.

I have added many details into the heading comment, and will add more with progression of this discussion. Those should help to dive into what I am trying to achieve and how this whole thing even works (or, at least, how it supposed to work). If some parts are incorrect or unclear, please, just write me and I will rewrite them.

That's great. Thank you very much. I'll try to go through it as soon as possible.
Sorry if it takes a while but it's really a lot of stuff to read and digest before moving on. 🙂
A quick question (and sorry if it sounds stupid but I still have to dig into your explanation).
Do I get it correctly that the whole thing doesn't apply to types for which the user doesn't have the control?
For example, imagine a third party hierarchy aimed to create UIs (cough coff Qt coff cough). I can't put its graphic items in my registry because I can't make them inherit from entt::polymorphic, is it correct?
Please, also ignore for a moment the fact that probably it doesn't even make sense to put these objects in the registry. It's just to provide an example. 😅

I'm not sure how physics libraries work, but if they have some sort of shape hierarchy, then it might be an example of non-extensible third-party class as well.

It is a good question, right now there are no way to declare hierarchy for third-party components. However it seems possible to add alternative way of declaring hierarchy separately from the classes. entt::inherit is just a template to form type_list of all parent types for given component type, and nothing stops such list from being created outside the component type itself. The only difficulty may be in hidden relation between entt::inherit and hacky wrapper implementation.

I'm trying to wrap my head around the implementation details. A bit at a time.
I'm not sure I get them correctly though. Please, correct me if I'm wrong.
Let's suppose there are 3 pools for types T1, T2 and T3. All these types derive from a common base B (polymorphic and inherit and all the rest, that part is pretty clear and I'll drop a bunch of questions/doubts later on probably 🙂).
When I add an instance of T2, what happens is that a wrapper is created within its pool while another two wrappers are also created in the pools for T1 and T3? All these wrappers have the size of 🤔 B plus a pointer?
I think I don't get what Component is here:
template<typename Component>
struct polymorphic_component_container;

That is, if it's the base type or the final type. This also makes it difficult to understand how this type is used.
Can you elaborate a little further on this point?

I suppose, you have hierarchy like this:
    B
+---|---+
|   |   |
T1  T2  T3

When you add component T2, it adds references to itself into all parent pools (B in this case), so you following structure:
pool T2: T2        // stores value of newly created T2
pool B : T2&       // stores no value, but has a reference to T2 value in T2 pool
// pools T1, T3 are empty

So T2 can be accessed both as T2 and as B.
When you add, for example T1, you will get the following:
pool T1: T1              // stores value of newly created T1
pool T2: T2              // still stores a value of T2
pool B : [T1&, T2&]      // still stores no value, but now has both reference to T2 value in T2 pool and T1 value in T1 pool
// pool T3 is still empty

Returning to your question about Component template parameter - it is a exact (not parent or child) type, that this wrapper can store by value. Only one value can be stored per wrapper, as there is only one component of this exact type can be attached to a single entity.
When attached to an entity, component (lets assume it is T2) is first put into corresponding pool of T2 into the wrapper for the same type, and then it will go through all of its parents and add reference to itself.
Hope this will help a bit.

Hope this will help a bit.

Yeah, definitely. Thank you a lot.
The first question that pops to my mind is the following: isn't it an issue when it comes to multithreading?
The design of EnTT makes it possible to add and remove (but even sort) components in parallel. In this case, if I decided to store aside a hierarchy like that of Qt where all items inherit from a QObject or QWidget type, multithreading the access to their pools isn't an option anymore.
Do I get it correctly? Standalone and fully independent pools are kinda expected most of the times.

Yes, it limits multithreading for polymorphic components, which share a parent, because accesses for this components will also affect shared parent pool. For polymorphic components only pools, related to separate hierarchies can be accessed in parallel.

Hope this will help a bit.

Yeah, definitely. Thank you a lot. The first question that pops to my mind is the following: isn't it an issue when it comes to multithreading? The design of EnTT makes it possible to add and remove (but even sort) components in parallel. In this case, if I decided to store aside a hierarchy like that of Qt where all items inherit from a QObject or QWidget type, multithreading the access to their pools isn't an option anymore. Do I get it correctly? Standalone and fully independent pools are kinda expected most of the times.

In the particular case of Qt, all QObject-based types are expected to only be used through pointer so storing them by value in a pool will be a bit complicated. On the other hand, storing pointers won't work with polymorphic storage because pointer types are not directly related through inheritance.
It has little to nothing to do with the proposal, just something to keep an eye on: sometimes you shouldn't store things by value by design.

It has little to nothing to do with the proposal, just something to keep an eye on: sometimes you shouldn't store things by value by design.

I think such problem will be solved along with adding the possibility to declare third party hierarchies, I assume that you will be able to say something like "A* is a parent to B*" for types, you want to store by pointer, instead of "A is parent to B" for what you want to store by value.

What about making this whole thing external with respect to the pools? Something like entt::registry::poly_for_each<Base, Derived1, Derived2,...>() that just iterates all those pools if they are present, returning a reference to the Base. As for functions like entt::registry::get(), I'm not sure how they can support polymorphic components - AFAIK, they assume that only one component of the given type is associated with an entity, it's impossible to achieve adequate behaviour without an optional<T&>.

entt::registry::poly_for_each<Base, Derived1, Derived2,...>()

Could be improved (kinda):
template< class T >
struct derived_types
{
  using value = entt::type_list<T>;
};

template<>
struct derived_types< Base >
{
  using value = entt::type_list< Base, Derived1, Derived2 >;
};

template< class... T >
entt::registry::poly_for_each (entt::type_list< T... >)
{
  entt::registry::each< T > ()...;
}

template< class T >
entt::registry::poly_for_each (...)
{
  entt::registry::poly_for_each (typename derived_types< T >::value{});
}

Yep, as I've said. However there are still performance issues.

And there can be dozens of child types, all of which will be required to check for each iteration, which is a major drawback, even if you fix the first one by separately declaring derived list once.

What if one implemented this with a storage mixin?
When a pool for a derived type is created, it registers itself as a candidate for elements that derive from a given base class.
Then you can just iterate all these pools to visit all the elements that derive from that class.

Mmm no, wait. What I'm saying is that all pools created with types that derive from B could register themselves on creation in a list (somehow, ignore the technical details for a moment).
The small set optimization would still apply here, since the size of B is just the sum of their sizes. Not sure why you would have to check all other pools for each entity instead, I'm kinda missing this point. 🤔
Anyway, just thinking aloud at the moment to see if we can have the cake and eat it. 🙂

Oh, I see now, dont know how I've missed this. In this way it will be a good solution, and the only cost will be just remembering already visited entities.
I can try implementing something like this in the upcoming days, what do you think?

Uhm, I mean, as you prefer. I won't stop you for sure. 🙂
At the moment I'm mostly throwing questions and random ideas at you to dig into the topic together. 😅
However, yeah, you're more than welcome if you want to experiment with different approaches to see if we can refine it.
I can share more details on what I have in mind if you like (tomorrow morning though, it's 7PM here).
Just let me know. See you and thanks for the discussion. 👋

Just to be clear, what I mean is something along this line.
This doesn't even require any change to the codebase and also solves the problem with multithreading.
If it feels hacky, that' because I packed the example in less than 30 minutes around midnight and so, yeah, it's hacky. 😅
However, it should give you a grasp of what I mean. Let me know if you've any doubts.

Yes, thank you a lot, I understand what you mean. I just was focused on the one solution I came up with, because I had such idea in mind before and wanted to implement it, it was obviously a mistake, I should have spend more time comparing different approaches.
Although it may provide some advantages like iterating several polymorphic components at once, those are just seems to be not so useful compared to the main disadvantages - how complex the implementation is and the multithreading one. And they can be implemented with your idea, maybe even with insufficient additional performance cost.
As for your solution, I have one doubt right now: because registering pools happens at runtime, we don't know the exact type inside them, so converting pointer between them might be a problem with multiple inheritance. Suppose you have this types:
struct A { int a; };
struct B { int b; }
struct C : public A, B {};

Now, when converting to from C& to B& we need to add 4 to the underlying pointer. When doing this conversion at the compile time, the compiler will do this for us in a right way, but at runtime it will become a problem.
dynamic_cast does not seem to be an option here, as the components can be anything (if we assume we can have external hierarchy declaration, and also they just might not be virtual). The one solution I can propose is storing pointer difference along with the sparse set somehow and then just do conversion by pointer arithmetic, but this one seems to be violating standard (although I think it will work in most compilers).
If we cant solve the above problem, then we will need to declare all children for each type, and I really want to avoid such requirement. If you will come up with a better solution, please, let me know.

Or don't allow multiple inheritance.

Yes, but I think it can be pretty useful, so it is not the best option, imho

Stepping back to earlier discussions, here I came up with some templates to allow hierarchy declaration in several different ways, it is now not dependent on entt::inherit and allows declaration outside of the type itself. Please, tell me, what do you think about it.

It's really a shame that we can't extract the base classes of a type. At least the most direct one. It's not that the compiler doesn't know about them, so why not? It would make a lot of things a lot easier.

I just was focused on the one solution I came up with, because I had such idea in mind before and wanted to implement it, it was obviously a mistake, I should have spend more time comparing different approaches.

It was not a mistake actually. It has its pros and cons while the road from point A to point B is never straight. 🤷♂

because registering pools happens at runtime, we don't know the exact type inside them, so converting pointer between them might be a problem with multiple inheritance

Yeah, for sure. When the this pointer changes in a hierarchy, my example breaks. It's just a proof of concept to show what I had in mind.
It's easy to solve though, at least at a first glance. We can bind a fake vtable with the pool and use it when needed. Something like this at the end of the day.

I came up with some templates to allow hierarchy declaration in several different ways

Far better imho. Lot of times we devs use third party libraries and it's important to desing things in such a way that they can also work with these tools. 👍

Thank you! I think now I will go and make an implementation, that could possibly already go into the library, so it would be easier to discuss it in details. I will post it here, when it will be ready.

Hello, again! I've at last got my hands on implementing the new approach. Sorry, if it took a while, unfortunately, last days were busy for me.
So here it is: https://github.com/zheka2304/entt/tree/polymorphic. It is smaller and much cleaner, than the previous one, and its based on ideas, that were proposed here, so it will be easier to describe. It lacks some functionality and not completely done yet, but it has the core features.
Lets first start with the updated polymorphic component declaration. Now, polymorphic components can be declared in different ways:

Old way using entt::inherit:

struct A : public entt::inherit<> {}; // base type
struct B : public entt::inherit<A> {}; // derived type

New way, by declaring parents externally:

struct A {}; // base type
struct B : A {}; // derived type

// hierarchy declaration
template<>
struct entt::poly_direct_parent_types<A> {
    using parent_types = type_list<>;
};
template<>
struct entt::poly_direct_parent_types<B> {
    using parent_types = type_list<A>;
};

Additionally, parent types can be declared manually inside a polymorphic type. However this one should be used with care, because if you wont redeclare type list, it could be inherited from a parent type without any warning.

struct A {
    using direct_parent_types = entt::type_list<>;
};
struct B : A {
    using direct_parent_types = entt::type_list<A>;
};

There are also some utils to determine, if a type is polymorphic, and for getting all parent types of a given type:
entt::is_poly_type_v<T>
entt::poly_parent_types_t<T>

Also, now polymorphic component hierarchy can be declared for pointers, instead of the components themselves:
template<>
struct entt::poly_direct_parent_types<A*> {
    using parent_types = type_list<>;
};
template<>
struct entt::poly_direct_parent_types<B*> {
    using parent_types = type_list<A*>;
};

In the above example A* will be considered polymorphic, and A will not. Implementation fully supports it by separately handling conversion between A* and B* by internally dereferencing them, so converting pointers with multiple inheritance will also work fine.
The registry now has three new methods:

poly_get_all<Type>(entity) - returns iterable to go through all components, derived from Type for a given entity
poly_get_any<Type>(entity) - returns pointer to the any component, derived from Type or nullptr
poly_each<Type>(func) - iterate all components in the registry, derived from Type

Now, lets move on to the core of the implementation. The example, given by @skypjack used emplace_hint to store child pools for given polymorphic types. This one works basically in a same way, but I've created separate class entt::poly_types_data to store and access all data related to polymorphic components in the registry. It allows to get polymorphic type data by given type, which gives access to all related pools via entt::poly_type and entt::poly_pool_holder classes.
entt::poly_type<Entity, Type> represents runtime data for one polymorphic type, it stores entt::poly_pool_holder for each child pool. It allows iterating through those pool holders, and iterating all components in those pools for a given entity by using specialized iterators.
entt::poly_pool_holder<Entity, Type> holds one child pool and converts components from this pool into Type. It implements one method - try_get, which will return converted pointer to Type or nullptr. Also it allows to access underlying pool as a sparse_set.
Sorry, if I've forgotten something, I still don't have much free time, so this text was written in a hurry. Please, write, if something is not clear or there are some mistakes. Thank you!

During the past few days I've worked on some improvements in the same branch, so here they are:

registry.poly_get_all, registry.poly_get_any and registry.poly_each and all polymorphic data containers, described above, are now able to correctly handle const qualifiers on input component types: using const Type instead of Type will result in passing back a const reference to the component. This is also applied for pointer components: requesting const Type* will result in const Type* to be passed back.

Added registry.poly_remove<Type>(entity) - a method to remove all polymorphic components, derived from Type for a given entity. Will return count of removed components. This one works by carrying additional function pointer in poly_pool_holder for removing component by entity from underlying pool.

Implemented signal support for polymorphic storage mixins. Before, on_construct, on_update and on_destroy weren't implemented for poly types, but now they are. Corresponding events are called for any parent component type, not only for exact type of the component. To allow listening events for non-constructible base classes, separate poly storage mixin is used for such types, that does not derive from storage and instead just allows signal handling.

I think right now it has most of the required functionality and the implementation is clean enough, so maybe I should move to polishing it and writing tests. Please, write your thoughts on it, I will appreciate any feedback.

It is located in a separate branch - https://github.com/zheka2304/entt/tree/polymorphic

I see, thanks. The first comments that come to my mind after a first glance:

Not sure I get the purpose of poly_sigh_holder and why you would want to trigger N events for the same elements. Signals are meant for things like resource cleanup and similar. I can't really imagine an use case for this complex mecahnism honestly.

polymorphic_data and all the functions added to the registry interface go somewhat against both the logic and the policy of this library. That is, currently I'm moving towards splitting the logic from the registry to also allow a registry less model. Therefore, adding more logic to the registry won't help. Moreover, this implementation makes me pay (as an user) for something that I don't want necessarily. That is why my suggestion was to use the context to store the relevant data.

Similarly, your mixin forces the signal support on the user. This isn't optional, you can't disable it as you can do with the built-in signals. Is it intended? How so?

What does the register_for_all_parent_types function do? It just appends the storage to a list of derived classes for all the base types of Type?

Thanks and good job!! 🙂

Thank you for your feedback!

I thought sometimes it might be useful to register signal for some base class, so it will be triggered when something is happening with any derived type. However, if signals are used mostly for something like resource cleanup, this is not very useful and better to be removed.
Fair enough, I will store and access polymorphic_data through the context, so it will be created, only if any polymorphic components are used. As for the new functions in the registry, if they should not be located there, what will be the best place for them in your opinion?
And for mixin I will separate signal handling part and polymorphic storage part of it, so user will be able to specialize polymorphic storage type without signal support.
Yes, it does exactly this. When looking at this right now, I think I should probably inline add_self_for_type function.

Hi, and sorry for my late reply.

Really, no need to apologize. 🙂
Open source works like this, we do our best when we have the time to do that. So, well, thank you for contributing!

I've recently read about observers and it seems to me that they might benefit from this idea.

Mmm, yeah, in theory it might be an option but I still can't figure out a proper use case in practice. Not sure it's worth it but let's keep it in a corner for later.

However I think, that even if we will decide to keep this feature, it should be disabled by default and enabled for certain component types manually, as it has a performance impact.

Definitely. Pay for what you use. I don't want to affect the normal uses with a corner case feature.

should I make algorithms independent from the basic_registry?

I think so 🤔 not sure if it's possible but it would be great if it only worked with storage classes and the like.

I've recently read about observers and it seems to me that they might benefit from this idea.

Mmm, yeah, in theory it might be an option but I still can't figure out a proper use case in practice. Not sure it's worth it but let's keep it in a corner for later.

Ok, I will move to separating signal handling and polymorphic parts of the mixin. There is not much code, and it should be rewritten anyway, so it is safe to clean it up for now.

should I make algorithms independent from the basic_registry?

I think so 🤔 not sure if it's possible but it would be great if it only worked with storage classes and the like.

Here is my idea, how it should look. I've made a type poly_types_accessor, that is used, to access polymorphic type data. It can be specialized for any type, and by default is specialized for basic_registry to access data from its context.
Then, I've created assure_poly_type<Component> function, that uses poly_types_accessor to get poly_type<Entity, Component> from given polymorphic data holder (for example, registry). This one does some type checks, gets entity type from the holder and handles const qualifiers. In general it provides us with a simple way to get polymorphic type data from some opaque data holder type by just calling assure_poly_type<T>(holder).
With it, implementing polymorphic algorithms, in a way, they don't rely on registry type becomes easy. What do you think about it?

You probably have the whole picture in mind and I'm glad. Although, honestly, I can't easily understand how it turns out. 😅
So, well, I'm tempted to say to give it a shot and see what happens. We can still refine it later eventually. 🤷♂

I've cleaned everything up, removed polymorphic header include in registry, so it can be included separately, only when it is required. I've also added some tests for polymorphic type traits and for algorithms & functionality.

So, well, I'm tempted to say to give it a shot and see what happens. We can still refine it later eventually. 🤷♂

Does this mean, I should open a pull request with what I have right now? And if it means yes, into which branch should I make it?

Well, opening a PR is probably the best way to make the code easy to review actually.
It doens't always mean that it will be merged but it helps to discuss and refine an idea most of the times.
What I do with your branch usually is to create a fake PR towards EnTT and look into the diff. So, well... 😅 🤷♂

Thank you for making it clear, I've created a pull request #871. Looking forward to continue our discussion there :)

Sounds good. I'm closing the issue then. Let's continue the discussione directly on the PR. 👍


Improve Dev Velocity for Terraform

Currently, when we write AWS infra using terraform, we have to run a set of manual commands to setup terraform along with validating + applying the tf plans. We should try to experiment with integrating these commands into dlp-cli. Below are some use cases we should add to the dlp-cli:
Deliverables

@MugPand , what instructions/steps did you follow to setup terraform?
a. Implement a dlp-cli command to setup terraform for our use for DLP. We keep all terraform files in dlp-terraform/ directory
Implement a dlp-cli command to be able to validate terraform schemas across all .tf files in the dlp-terraform directory. We validate .tf files using terraform validate
Implement a dlp-cli command to be able to apply a .tf file by creating the resources in AWS. Eg: something like dlp-cli terraform apply dynamodb/ should run terraform apply within the dlp-terraform/dynamodb path for dynamodb.tf file
Modify our github actions checks to ensure that for a given .tf file, it's under a folder within dlp-terraform (like check valid folder schema within dlp-terraform directory

@michellewliang if you don't have Terraform already, here's the instructions: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli

Adding @abhinavish to this as well. You guys can split up the deliverables however you like.
I can foresee these all being separate PRs.

For now, I think @michellewliang can do 1 and 2, and @abhinavish can do 3 and 4.

@MugPand , status on this?


Label model implementation of Snorkel 0.9.1

Hi all,
I am looking at Label Model of Snorkel version 0.9.1. But I am not getting from which research paper of Snorkel, Label Model is implemented in Snorkel version 0.9.1.
I really want to know how Label Model is implemented and from which research paper the concepts are integrated in Label Model of Snorkel version 0.9.1
Thanks in Advance

Hi @brijendra2496 you can check out the API docs for many questions like these!  https://snorkel.readthedocs.io/en/v0.9.3/packages/_autosummary/labeling/snorkel.labeling.LabelModel.html#snorkel.labeling.LabelModel


Use Leafwing Input Manager

https://github.com/leafwing-studios/leafwing-input-manager

Make sure to use KeyCodes: https://github.com/bevyengine/bevy/pull/5495

Blocked by https://github.com/Leafwing-Studios/leafwing-input-manager/issues/179


Unable to use splunk action

SUMMARY
I have a stackstorm installed v3.8.0 and i installed the splunk pack the problem is that after install i cant find the actions of the splunk on user portal, on the pod i can the actions dir is created.
STACKSTORM VERSION
Paste the output of st2 --version: st2 3.8.0, on Python 3.8.10
OS, environment, install method
Stackstorm is running on Kubernetes
Steps to reproduce the problem
st2 pack install splunk -t TOKEN
st2 action list -t TOKEN
Expected Results
Expected result after installing splunk pack use available actions
Actual Results
Using the UI no splunk actions was found, but when i check the directory on the pod i can see the actions directory is created

I checked if the pack is installed with the command st2 pack list and i can see that is there.

Thanks!

are you installing this on a pod?  If so there is a helm chart for stackstorm you should use.  st2 pack install doesn't work in docker environments due to the nature of pods not saving state.


feature flag to interop with rust::geo

Hello, thanks for the great crate.
A nice-to-have feature-flag would be to allow directly converting geojson::PolygonType to geo::Polygon. I don't know in which create it should live. I assume it's reasonably frequent to use those two together
for now doing that:
fn vec_to_line(vec: &Vec<Vec<f64>>) -> LineString<f64> {
    vec.iter()
        .map(|coord| (coord[0], coord[1]))
        .collect::<Vec<_>>()
        .into()
}

fn polygon_to_polygon(polygon: &PolygonType) -> geo::Polygon {
    let mut copy_vec = polygon.clone();
    let holes = copy_vec.split_off(1);
    let line = vec_to_line(&copy_vec[0]);

    geo::Polygon::new(line, holes.iter().map(vec_to_line).collect())
}

https://docs.rs/geojson/latest/geojson/#use-geojson-with-other-crates-by-converting-to-geo-types

Thanks 👍


dstftw - GPG Public Key

@dstftw
Heya, your public key doesn't seem to be on any of the keys servers, I'd like to be able to check the sig of the Windows release.
Thanks.

It's over here.

@dstftw Do you mind publishing it on a widely-used keyserver, like https://pgp.mit.edu ? That helps in a lot of setups.

@phihag I'm fine with that.


Update README.md

Expanded the intro. Testing if I can use git operations like fork and pull requests on GitBooks.

Thanks Paul.


Warn/Raise if trying to install a package not specified as a dependency

We wrote a noxfile which has a session that installs dev dependencies that were accidentally not specified in the pyproject file.  It got me thinking that a warning or an error if we were trying to do that might be a nice feature for non-poetry.  I'm not totally sure how that would be detected efficiently though.

This used to be nox-poetry behavior when requirements were still exported with hashes. Unfortunately, this is no longer possible because pip dropped support for hashes in constraints files, see #222. To be frank, I'm hesitant to introduce logic in nox-poetry to handle this, as I prefer to keep this package restricted to the minimal glue code for Poetry and Nox. (To be precise, the minimal glue code required to get pinned installations of subsets of development dependencies.) I'm open for suggestions though how this could be achieved.


Standard Deviations on Bollinger Bands

Good day, I just wanted to know if it would be possible to change the standard deviation on BBANDS with this library? I'm looking at the test file and it's clear that you can check to see if the standard deviation is 2, but I see no indication that this can be changed to a std dev of 1 or 3 for example, could you clarify this? I did try some testing in my application but I'm not very familiar with TS and the library to know if this is even possible.
Thanks!

Hi @Smackface, it is absolutely possible to set the standard deviation multiplier yourself. Just pass it to the constructor of BollingerBands: https://github.com/bennycode/trading-signals/blob/v3.6.1/src/BBANDS/BollingerBands.ts#L32
Example:
import {BollingerBands} from 'trading-signals';

const deviationMultiplier = 3;
const bands = new BollingerBands(5, deviationMultiplier);

Best,
Benny


Its not running on the top of linux docker is containers right this docker images not working

If i understand you correctly - no, this image wont working on linux machine, only on Windows OS

IIS docker image supports only Windows OS.


arm64: remove unnecessary trace interface

Summary
this is an old implementation for ARM64 trace, but will fail to
compile when CONFIG_SCHED_INSTRUMENTATION_SWITCH is enabled.
Remove it, since it will never be used for trace framework.

Impact
None
Testing
PASS

@qinwei2004 please fix the message commit to remove the typos, suggestion:
Summary
    this is an old implementation for ARM64 trace, but will fail to
    compile when CONFIG_SCHED_INSTRUMENTATION_SWITCH is enabled.
    Remove it, since it will never use for trace framework.

@acassis
it's done


fix: redo whole deepl style

@watatomo before i approve is https://github.com/catppuccin/userstyles/issues/183 related to this in any form?

@isabelroses nope. i didn't even see that issue 💀

@isabelroses nope. i didn't even see that issue 💀

Okay that's cool, ill go ahead and approve, you can merge whenever you like.


Add CallbackQuery with game_short_name can be processed

Hi!
I was testing tourmaline for a possible replacement for my telegram api client and I really liked it.
But the key functionality for me is the game callback answer unfortunately not implemented.
require "tourmaline"
GAME_NAME = "my_game_name"

class TelegramBot < Tourmaline::Client
  @[OnCallbackQuery(GAME_NAME)]
  def process_query(ctx)
    game = ActiveGame.process_update(ctx.query)
    answer_callback_query(ctx.query.id, url: game.player_a_route.url)
  end
end

So the game callback is handled fine in my app.
Thanks you.

I don't know much about the game_short_name property since I haven't done much of anything with games. Would it ever be supplied along with data, or would it generally be an either-or thing?

As described callbackquer Exactly one of the fields data or game_short_name will be present.

Right. Thanks for this!

Excellent, Thank you!
if it comes in handy for the documentation, I made a  gist how to just add an HTTP::Handler for Tourmaline bot in to Lucky.


Feature: slash command

It would be great to have a slash command ready to be used (in core or as an example), see the notion like experience.

This is awesome. Thx all!


Replace ':' with '.' in GC mark

A valid Kubernetes label may only contain alphanumeric characters, '-',
'_' or '.', and must start and end with an alphanumeric character (e.g.
'MyValue',  or 'my_value',  or '12345'.

Replaced by #1806 as this branch name is going to be confusing if it shows up in the merge commit.


Updated for Swift 5.

Updates necessary for a clean build under Swift 5.

Any chance to merge this PR in the near future?


[858] Remove paas monitoring

Trello card URL
https://trello.com/c/sPSYOhve
Changes in this PR:
Remove code and docs

 TV: remove paas monitoring


Support for date and date-time type casting

It would be great to have type casting of formats 'string/date-time' and 'string/date' to python datetime.datetime and datetime.date.
I guess this would need custom flask converters to be added to url_map (http://flask.pocoo.org/docs/0.11/api/#flask.Flask.url_map)

@cbornet You have access to the Flask.app using the attribute .app from the object connexion.App. So you can use the Flask converters you want. And for the payloads you can also add custom converters, please see an example here: http://connexion.readthedocs.io/en/latest/cookbook.html#custom-type-format

Thanks for your link but it seems it's only for format validation, not conversion.
I think what would be needed is to enhance Operation::get_path_parameter_types() to also read the format and PATH_PARAMETER_CONVERTERS for date and date-time

@cbornet You are right. Are you planning on working in a PR for that?

Any plans to get this implemented? It's a real shame that a type as common as date isn't automatically casted by connexion and requires us to litter our controller code with custom calls to deserialize_date


Version 1.1.2 That's for 1.19-1.19.2 Works on 1.19.1, but NOT 1.19.2

Hello! This is my first github submission, I made an account for this :)
As you read in the title, Version 1.1.2 That's for 1.19-1.19.2 Works on 1.19.1, but NOT 1.19.2. I tested the popular addon pack "Additional Elytras" with CIT Resewn, works perfectly in 1.19.1. On 1.19.2, it sadly doesn't. Same environment in both tests.
The pack allows you to change Elytra skins by renaming it. The test case I used was "Demon Wings" Elytra. With same circumstances, on 1.19.1 it showed up in inventory AND as a model outside. Worked flawlessly. Sadly, nothing happened on 1.19.2.
I hope we can find a fix for the issue soon! Thank you for what you're doing :)

Another note: Same happened with my friend. I was on 1.19.1, my friend was on 1.19.2, with the same version of CIT Resewn. Using textures from the same resource pack "Additional Elytras", which includes Invisible armor if you rename it to "invisible", I could see both our renamed "Invisible" armors as invisible, while my friend couldn't!

Works perfectly fine for me on 1.19.2. Gonna need you to send the logs if you want help troubleshooting.

The log isn't saying anything, it's irrelevant to the issue.
Open the game and load the pack fully, then close the game and send the logs from that.

Yep! Here's the logs: https://paste.ee/p/XbjEL

There isn't anything that should stop it from working, I've tested and had the demon wings working on 1.19.2(albeit with broken paths enabled in the config).
Something interesting that caught my eye though is that citresewn isn't reporting anything during resource loading, can you send the config file for cit resewn? (config/citresewn.json)


Dockerfile for ROCM

FIxes for https://issues.redhat.com/browse/RHOAIENG-4368
Description

Docker file for ROCM based on: https://github.com/ROCm/ROCm-docker/blob/master/dev/Dockerfile-centos-7-complete
How Has This Been Tested?

Merge criteria:

[x] The commits are squashed in a cohesive manner and have meaningful messages.
[ ] Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
[x] The developer has manually tested the changes and verified that the changes work

Great! Could you also address the code static analysis failures?

tested these with : https://quay.io/repository/harshad16/amd-base?tab=tags


Use guid instead of updated_at in policy table to mark a  policy.

[#142233327]

Merged.
Next time run all the tests.


RTM update of part2 Intro to MVC

@rachelappel  please review

@rachelappel  hold off, I've got some complicated build issues I need to sort out.

@rachelappel please review
Why does this have merge conflicts?

@Rick-Anderson We can find out when it's merge time. Git will tell us.

Merged 445b3987d337989084e77f469ece3b639027caf6


ERROR: couldn't find TuplestoreScan node in combiner's plan

Centos6.5   Pipelinedb 0.9.7
After run for some time or restart ,the pipelinedb didn't work. And the log show this error.
After deactivate the two continuous view (  history_user_mac_day 、history_user_hourly  ) , the pipelinedb work again , but the error message still exist !   Only rebuild them can fix the problem.
I had share my sql . Who knows what this is about?
error message
``
2017-06-20 18:14:09.276 CSTERROR:  couldn't find TuplestoreScan node in combiner's plan
2017-06-20 18:14:09.278 CSTLOG:  worker process: combiner2 [test] (PID 10986) exited with exit code 1
2017-06-20 18:14:09.281 CSTLOG:  pipelinedb process "combiner4 [test]" running with pid 11030
2017-06-20 18:14:09.369 CSTERROR:  couldn't find TuplestoreScan node in combiner's plan
2017-06-20 18:14:09.371 CSTLOG:  worker process: combiner4 [test] (PID 11030) exited with exit code 1
2017-06-20 18:14:09.522 CSTLOG:  pipelinedb process "combiner0 [test]" running with pid 11033
2017-06-20 18:14:09.661 CSTERROR:  couldn't find TuplestoreScan node in combiner's plan
2017-06-20 18:14:09.663 CSTLOG:  worker process: combiner0 [test] (PID 11033) exited with exit code 1
``
sql
CREATE STREAM ap_sta_stream (
ap_mac text,
client_mac text,
riss INT,
stamp timestamp,
noise int,
channel int,
sourcetype int);
create continuous view history_user_mac_day WITH (ttl = '2 day', ttl_column = 'ts') as
select day(s.stamp) as ts,b.level1,s.client_mac
from ap_sta_stream s
join wifi_ap_unit_info b on s.ap_mac=b.ap_mac
group by ts,b.level1,s.client_mac;
create continuous view history_user_hourly WITH (ttl = '3 month', ttl_column = 'ts') as
select hour(clock_timestamp()) as ts,
(new).level1,
dumbloom_contains(t.users, (new).client_mac) as flag,
count(dumbloom_contains(t.users, (new).client_mac)) as uniques
from output_of('history_user_mac_day') s
join wifi_bloom t on 1=1
group by ts,level1,flag;

@WeiYu53111 can you try running the latest release update, 0.9.7u4? We have seen this issue before (although rarely), so we added some logging in that update that will give us more information in the error when it does occur.

hi ,@derekjn . I install the release update, 0.9.7u4 on a new machine and then use the pipeline-dump to export the continous view ( history_user_mac_day, history_user_hourly)  to a sql file.   After restore the view and data.  I  insert one data to the stream ,the error show again ,but the error message just like befor.
error message
2017-07-10 19:58:11.977 CSTERROR:  couldn't find TuplestoreScan node in combiner's plan: 129
2017-07-10 19:58:11.979 CSTLOG:  worker process: combiner3 [test] (PID 28869) exited with exit code 1
2017-07-10 19:58:12.986 CSTLOG:  pipelinedb process "combiner3 [test]" running with pid 29547

@derekjn   I have just sent you<EMAIL_ADDRESS>)  an emil  which have the step to make error show again.

@WeiYu53111 it is almost like before, except for this crucial part:
<previous message>: 129  <--- new!

That little bit is actually pretty helpful for us, so we're looking into this now. Thanks so much for coming back1

@WeiYu53111 I can confirm that we were able to finally reproduce the issue with the resources you emailed me--thanks so much!
A fix should be imminent.

@WeiYu53111 we just published an updated release that includes the fix for this issue. Thanks again for following up with all of the helpful information!
https://github.com/pipelinedb/pipelinedb/releases/tag/0.9.7u5


Update to ASM 9.7.1

What feature do you want to see added?
ASM 9.7.1 has been released.  A pull request proposing it for Jenkins core has arrived as:

https://github.com/jenkinsci/jenkins/pull/9831

Upstream changes
6 October 2024: ASM 9.7.1 (tag ASM_9_7_1)

new Opcodes.V24 constant for Java 24
Javadoc improvements
new features

318013: new ClassWriter setFlags() method.
Add ConstantDynamic serialization and Number suffixes to Textifier.

bug fixes

318014: Analyzer with a SimpleVerifier may throw an AnalyzerException on valid java code due to incompatible frame locals.
318015: Valid bytecode for jvm, but failed to pass the CheckClassAdapter.
318016: ClassNotFoundException with an array of the type of current class.
318018: changing invokedynamic Handle itf bool flag doesn't create new methodref in symbol table.
318019: Attribute::write is invoked twice.
Fix DUP_X1, DUP_X2, DUP2_X1, and DUP2_X2 not copying values correctly in Analyzer.
Fix SimpleVerifier multiple dimensions merge.
Fix SourceInterpreter wrongly saying that Condy long / doubles are one word elements.
GeneratorAdapter: fix push(Type.VOID_TYPE).
Fix null method parameter name in Asmifier causing NPE.

Are you interested in contributing this feature?
Dependabot or Renovate pull request is easier to handle, though it will need an extra label added in order to create the release.

Fixed by https://github.com/jenkinsci/asm-api-plugin/pull/49
CD will release it in some moments


Test jupyter serverextension

Added a test for jupyter serverextension.
I also changed the source to PyPI because the GitHub tag seems to have been altered. (The sha256 was failing.)
See https://github.com/conda-forge/notebook-feedstock/pull/1#issuecomment-210765721

Hi! This is the friendly conda-forge-admin automated user.
I just wanted to let you know that I linted all conda-recipes in your PR (recipe) and found it was in an excellent condition.

LGTM. However, I don't have permissions here.

Let's wait for @pelson since we was the original author of the recipe and he was the one that spotted my mistake.

@ocefpaf - if you wanted to remove the GitHub usage, there is some simplification that can happen to this recipe (removal of nodejs for one).
Thanks for following through on adding the test! :+1:

@ocefpaf - if you wanted to remove the GitHub usage, there is some simplification that can happen to this recipe (removal of nodejs for one).

The only reason I used PyPI here was because the sha256sum failed and I suspected that the source had changed (that can happen on GitHub, but no PyPI since GitHub allow you to delete and re-release the same version). I reverted because it seemed to be a download issue and not a real change. Let's see how it goes now.

I do lean towards the Debian approach on this, but am pragmatic about the cost of doing so (and gave up on doing it for ipywidgets as I couldn't get it to work on Windows).

I agree with that. If only we had time to do it properly everywhere...

So I'm going to merge this as is. For full transparency, @ocefpaf has reverted the GitHub/PyPI change (as it turned out to be the simpler PR), but I'm still very happy to discuss this one further. Maybe an agenda item for our next hangout on Fri 29th April (1400 UTC)?


Option to disable away notice messages

I'm really not interested in away notifications for most servers, could we have an option to disable them?

What away notifications? The ones server sends you when you talk to someone who is away?

No, the notice messages in the server room. I believe they're generated from https://github.com/hifi/heisenbridge/blob/06d2d445edd891ab06e95fe8cf7533fd30328b8a/heisenbridge/network_room.py#L1958-L1961

CAPS --remove away-notify in network room and then reconnect.

Ah thanks. I guess enabling this I was hoping for the away status to show up on the user profile/room member list somehow.


Insert subresource hints

We can inform the preload scanner about resources via headers and link tags.  We should store what rewritten resources a page uses in the property cache and experiment with hinting them.
See:

https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/
https://www.w3.org/TR/preload/

@morlovich has been working on pushing for H2, and in H1 this knowledge about what includes what will probably be surfaced as rel=preload hints.


UI not persisting ID/Secret on reboot

Nocturne had been working great for me for about two weeks, but today I replaced my pi sd card with another one (refollowed the tutorial), and now when rebooting the Car Thing (I have it connected with a toggle USBC Cable) or rebooting the pi (Zero 2W), all I am greeted with is the login prompt, whereas before, it logged me in automatically.
I might've missed a step in the tutorial, but I don't believe I did, as everything works properly once I'm signed in. I can just use autofill on my phone to make it slightly faster, but the ideal solution is booting in while saving the credentials like before.
Any ideas? I wasn't sure if this belonged here or in nocturne-ui, so apologies if it's in the wrong place.

Hi! Could you join our Discord and DM me your client ID so I can try clearing it from the DB? Thanks!

Hi! Could you join our Discord and DM me your client ID so I can try clearing it from the DB? Thanks!

Thanks for the quick reply! I joined, however Discord won't let me DM you the ID:
"Your message could not be delivered. This is usually because you don't share a server with the recipient or the recipient is only accepting direct messages from friends. You can see the full list of reasons here:"

resetting the database fixed the login issue


ServerRouter - Invariant Violation: Browser history needs a DOM

Version
4.0.0-alpha.4
Test Case
Following - https://react-router.now.sh/ServerRouter
Steps to reproduce
Following - https://react-router.now.sh/ServerRouter
Expected Behavior
static markup being displayed in browser
Actual Behavior
~/react-app/node_modules/invariant/invariant.js:49
    throw error;
    ^

Invariant Violation: Browser history needs a DOM
    at invariant (~/react-app/node_modules/invariant/invariant.js:42:15)
    at createBrowserHistory (~/react-app/node_modules/history/createBrowserHistory.js:51:102)
    at History.setupHistory (~/react-app/node_modules/react-history/History.js:43:20)
    at History.componentWillMount (~/react-app/node_modules/react-history/History.js:50:10)
    at ~/react-app/node_modules/react/lib/ReactCompositeComponent.js:347:23
    at measureLifeCyclePerf (~/react-app/node_modules/react/lib/ReactCompositeComponent.js:74:12)
    at ReactCompositeComponentWrapper.performInitialMount (~/react-app/node_modules/react/lib/ReactCompositeComponent.js:346:9)
    at ReactCompositeComponentWrapper.mountComponent (~/react-app/node_modules/react/lib/ReactCompositeComponent.js:257:21)
    at Object.mountComponent (~/react-app/node_modules/react/lib/ReactReconciler.js:47:35)
    at ReactCompositeComponentWrapper.performInitialMount (~/react-app/node_modules/react/lib/ReactCompositeComponent.js:370:34)

ServerRouter replaces BrowserRouter. I'm guessing your <App> has a <BrowserRouter> inside it. On the server wrap your app in <ServerRouter>, in the client wrap it in <BrowserRouter>.

ahh, I see, I have been following the example too blindly, side effect of copy paste. Didn't realize Router is referring to BrowserRouter
import Router from 'react-router/BrowserRouter';

Thanks!

I got similar error when I was running jest tests. By adding --env=jsdom to the jest command-line problem solved. :crocodile:

It's called <StaticRouter> now, not <ServerRouter>.

thanks


Code formatting

The code format is a bit messy. I could make a clang-format file that is close to what most of the code looks like?

The code is very messy. Some of it started on Mac decades ago, went to Windows and now back to Mac again. Inconsistent usage of tabs and spaces, etc. A clang-format file would be nice. I believe VSCode supports those or supports an extension that supports. Probably does not help those who use Visual Studio though.

I think my format file is already in HinTaks repo. I didn’t apply it, yet. So you can try and maybe edit it before we apply it to the whole source.

Yes, the clang-format file is already in mine. I would prefer that the more obvious warnings get fixed first before large cosmetic changes though. I know I broke my own preference, changing all the mac-roman encoded comments and win 1252 comments into unicode (this is a "cosmetic" change in my book) but it is an extension of the non-ascii wide character literal fix, which is a code fix...
It was quite surprising to find non-ascii comments of the mac-roman encoded type and win 1252 type, (and in one file, both types in different sections). It certainly suggests a very long and pre-unicode history of the code base, as well as it having passed between mac and windows.


resource/cloudflare_waiting_room: Add queueing_status_code to the Waiting Room resource

Waiting Room has a new configuration field queueing_status_code that determines what HTTP status code is returned to a user while in the queue.  Adds support for queueing_status_code to the Waiting Room resource.
Depends on cloudflare/cloudflare-go#1357

acceptance tests all looking good
TF_ACC=1 go test ./internal/sdkv2provider -v -run "^TestAccCloudflareWaitingRoom_" -count 1 -timeout 120m -parallel 1
=== RUN   TestAccCloudflareWaitingRoom_Create
=== PAUSE TestAccCloudflareWaitingRoom_Create
=== CONT  TestAccCloudflareWaitingRoom_Create
--- PASS: TestAccCloudflareWaitingRoom_Create (15.38s)
PASS
ok  	github.com/cloudflare/terraform-provider-cloudflare/internal/sdkv2provider	15.845s


update packages

:white_check_mark: Build TheIdServer 4.4.1-fix-dependencies1-0095 completed (commit https://github.com/Aguafrommars/TheIdServer/commit/6589a4c6c0 by @)


Turbine Valve crashing the game

Issue description:
I am playing on a Resonant Rise 3 modpack for minecraft 1.10.2 and tried to build a fusion reactor with steam turbine. But everytime I place the turbine valve it crashes my game and I have to manually delete the block from my world using MCEdit. I tried to download older versions of mekanism, mekanism generators and mekanism tools but nothing seems to fix it.
Steps to reproduce:

Log into the world
Place the turbine valve anywhere on the world
the game crashed completely

Version (make sure you are on the latest version before reporting):
Forge: <IP_ADDRESS>1
Mekanism: <IP_ADDRESS>
Other relevant version: minecraft 1.10.2
If a (crash)log is relevant for this issue, link it here: (It's almost always relevant)
https://pastebin.com/v1VbBPkx

already fixed in dev


Nested Coroutine Valgrind Error

I was attempting to write a nested coroutine, and kept getting errors.  Here's a simple test case of what I was trying to do:
#include <iostream>

#include "generator.hpp"

cppcoro::generator<int> nested() {
  for (int i = 0; i < 10; i++) {
    co_yield i;
  }
}

cppcoro::generator<int> outer() {
  for (auto inner : nested()) {
    co_yield inner;
  }
}

int main() {
  for (const auto& value : outer()) {
    std::cout << value << std::endl;
  }
  return 0;
}

Running that program through valgrind yields the following errors:
==22418== Memcheck, a memory error detector
==22418== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22418== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==22418== Command: ./test
==22418==
0
1
2
3
4
5
6
7
8
9
==22418== Invalid read of size 4
==22418==    at 0x401E36: nested() [clone .destroy] (test.cxx:0)
==22418==    by 0x403250: destroy (coroutine:130)
==22418==    by 0x403250: cppcoro::generator<int>::~generator() (generator.hpp:163)
==22418==    by 0x4025A9: outer() [clone .resume] (test.cxx:12)
==22418==    by 0x4033D6: resume (coroutine:123)
==22418==    by 0x4033D6: cppcoro::detail::generator_iterator<int>::operator++() (generator.hpp:108)
==22418==    by 0x401818: main (test.cxx:18)
==22418==  Address 0x60b4280 is 208 bytes inside a block of size 264 free'd
==22418==    at 0x4C30D18: free (vg_replace_malloc.c:530)
==22418==    by 0x401E31: nested() [clone .destroy] (test.cxx:5)
==22418==    by 0x403250: destroy (coroutine:130)
==22418==    by 0x403250: cppcoro::generator<int>::~generator() (generator.hpp:163)
==22418==    by 0x4025A9: outer() [clone .resume] (test.cxx:12)
==22418==    by 0x4033D6: resume (coroutine:123)
==22418==    by 0x4033D6: cppcoro::detail::generator_iterator<int>::operator++() (generator.hpp:108)
==22418==    by 0x401818: main (test.cxx:18)
==22418==  Block was alloc'd at
==22418==    at 0x4C2FB6B: malloc (vg_replace_malloc.c:299)
==22418==    by 0x4EC1B79: operator new(unsigned long) (in /usr/lib64/libc++.so.1.0)
==22418==    by 0x400C73: nested() (test.cxx:5)
==22418==    by 0x40228B: outer() [clone .resume] (test.cxx:12)
==22418==    by 0x4032BC: resume (coroutine:123)
==22418==    by 0x4032BC: cppcoro::generator<int>::begin() (generator.hpp:177)
==22418==    by 0x401762: main (test.cxx:18)
==22418==
==22418== Invalid read of size 4
==22418==    at 0x402B0A: outer() [clone .destroy] (test.cxx:0)
==22418==    by 0x403250: destroy (coroutine:130)
==22418==    by 0x403250: cppcoro::generator<int>::~generator() (generator.hpp:163)
==22418==    by 0x40179E: main (test.cxx:18)
==22418==  Address 0x60b4110 is 208 bytes inside a block of size 296 free'd
==22418==    at 0x4C30D18: free (vg_replace_malloc.c:530)
==22418==    by 0x402B05: outer() [clone .destroy] (test.cxx:11)
==22418==    by 0x403250: destroy (coroutine:130)
==22418==    by 0x403250: cppcoro::generator<int>::~generator() (generator.hpp:163)
==22418==    by 0x40179E: main (test.cxx:18)
==22418==  Block was alloc'd at
==22418==    at 0x4C2FB6B: malloc (vg_replace_malloc.c:299)
==22418==    by 0x4EC1B79: operator new(unsigned long) (in /usr/lib64/libc++.so.1.0)
==22418==    by 0x4010F3: outer() (test.cxx:11)
==22418==    by 0x401751: main (test.cxx:18)
==22418==
==22418==
==22418== HEAP SUMMARY:
==22418==     in use at exit: 0 bytes in 0 blocks
==22418==   total heap usage: 3 allocs, 3 frees, 1,584 bytes allocated
==22418==
==22418== All heap blocks were freed -- no leaks are possible
==22418==
==22418== For counts of detected and suppressed errors, rerun with: -v
==22418== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Here's the line used to compile the program:
clang++ -std=c++17 -fcoroutines-ts -stdlib=libc++ -g test.cxx -o test

And here's my clang version:
clang version 5.0.1 (tags/RELEASE_501/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

So, what am I doing wrong?

Awesome!  That did the trick.  Thanks!


[flutter_adaptive_scaffold] ☂ Animations Need Work

Proposal
Animations in flutter_adaptive_scaffold need work.

[ ] The animations on window resize aren't snappy.
[ ] Animating out shows empty content

The duration of the animations are set to 1 second, we should have the option to set animation durations when creating slot layouts.

There's also a clipping issue when using this package with go_router: https://github.com/flutter/flutter/issues/116685

SlotLayout allows us to use custom animations for slots coming in and out, but we are unable to specify the duration or easing. It would be helpful if we add some parameters that allow for these adjustments.
SlotLayoutConfig
class SlotLayoutConfig extends StatelessWidget {

  const SlotLayoutConfig._({
    super.key,
    required this.builder,
    this.inAnimation,
    this.outAnimation,
    this.inDuration = const Duration(milliseconds: 100),
    this.outDuration,
    this.inCurve = Curves.linear,
    this.outCurve = Curves.linear,
  });

  final WidgetBuilder? builder;
  final Widget Function(Widget, Animation<double>)? inAnimation;
  final Widget Function(Widget, Animation<double>)? outAnimation;
  final Duration inDuration;
  final Duration? outDuration; // Use inDuration if not specified
  final Curve inCurve;
  final Curve outCurve;

  ...
}

Then we can update the SlotLayout.from method to add slots that use custom animations in or out with their own easing and durations.
static SlotLayoutConfig from({
    WidgetBuilder? builder,
    Widget Function(Widget, Animation<double>)? inAnimation,
    Widget Function(Widget, Animation<double>)? outAnimation,
    Duration inDuration = const Duration(milliseconds: 100),
    Duration outDuration = const Duration(milliseconds: 100),
    Curve inCurve = Curves.linear,
    Curve outCurve = Curves.linear,
    required Key key,
  }) =>
      SlotLayoutConfig._(
        builder: builder,
        inAnimation: inAnimation,
        outAnimation: outAnimation,
        inDuration: inDuration,
        outDuration: outDuration,
        inCurve: inCurve,
        outCurve: outCurve,
        key: key,
      );


Compile-AppInNavContainer() compatibility fix for alc.exe interaction

Compile-AppInNavContainer():379 was recently improved by enclosing paths provided to alc.exe in double-quotes.

$alcParameters = @("/project:""$appProjectFolder""", "/packagecachepath:""$appSymbolsFolder""", "/out:""$appOutputFile""")

This can cause alc.exe to fail execution for paths ending in a single DirectorySeparatorChar . At least alc.exe argument /project has proven to be problematic on my site: https://github.com/microsoft/AL/issues/4456
Compile-AppInNavContainer() could implicitly prevent such a situation by normalizing provided paths to either end without  or with the required pair of DirectorySeparatorChars.
Potential Fix
I've chosen to replace a single, terminal DirectorySeparatorChar with a pair accordingly, but removing it seems to be fine as well.
function normalize()
{
    # https://github.com/microsoft/AL/issues/4456
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string] $path
    )
    $normalizedPath = (Convert-Path $path)
    return $(if($normalizedPath.EndsWith([System.IO.Path]::DirectorySeparatorChar)) {
        "$normalizedPath$([System.IO.Path]::DirectorySeparatorChar)"
    }else{
        $normalizedPath
    })
}

# Prepare test-data

if($env:OS.ToLower().contains('windows')) {
    $PathA = 'C:/tmp/fabian/projectdir'
    $PathB = 'C:/tmp/fabian/projectdir/'
    $PathC = 'C:/tmp/fabian/projectdir//'
    $PathD = 'C:\tmp\fabian\projectdir'
    $PathE = 'C:\tmp\fabian\projectdir\'
    $PathF = 'C:\tmp\fabian\projectdir\\'
} else {
    # assuming MacOS
    $PathA = '/Users/fabian/projectdir'
    $PathB = '/Users/fabian/projectdir/'
    $PathC = '/Users/fabian/projectdir//'
    $PathD = '\Users\fabian\projectdir'
    $PathE = '\Users\fabian\projectdir\'
    $PathF = '\Users\fabian\projectdir\\'
}

$PathCollection = @($PathA, $PathB, $PathC, $PathD, $PathE, $PathF)

# Properly format paths to meet requirements as per https://github.com/microsoft/AL/issues/4456
foreach ($path in $PathCollection) {
    Write-Host $(normalize($path))
}

Output
C:\tmp\fabian\projectdir
C:\tmp\fabian\projectdir\\
C:\tmp\fabian\projectdir\\
C:\tmp\fabian\projectdir
C:\tmp\fabian\projectdir\\
C:\tmp\fabian\projectdir\\

best
fabian

Wouldn't it be easier just to use .TrimEnd('/') on the paths to remove trailing slashes or backslashes?
Doubling the slashes seems to be a workaround to a problem, which eventually some day might work differently I think.

yes, it would. Depending on what happens afterwards with the path. In my case there is lot's of upcoming code where I can not be certain whether some portion wasn't relying on at least a trailing DirectorySeparatorChar at some point for branching. So I decided to go with a DirectorySeparatorChar pair, but as mentioned... alc.exe itself seems to be perfectly happy wither either:

no DirectorySeparatorChar
or a pair of them

Obviously, the problem is that the \ in front of the " will escape the ". So the problem isn't really in the path.
I will proceed to trim end string to avoid the escape.

Shipped in <IP_ADDRESS>


Tooltipps translations will not work for added Lines in edit mode.

STR:

Test for existing DoD in a Task with one of the existing loclale (de_DE)
» Translation for all Icons will work
Click "+" in last DoD-line to add a row
» new line appears
Hover mouse pointer over "Add row" icon in this line

"Close Row" without translation, although translation does work for row above 😥

Can you create a pull request for your translator branch? Then I can try to reproduce it on my side.
As far as I can see, 'Close row' is not translated in your array, yet
https://github.com/RainerBielefeld/DefinitionOfDone/blob/main/Locale/de_DE/translations.php


Use confirmations instead of time to decide if tx is "safe" for mining

This should ensure that all nodes arrive at the same decision most of the time.

This basically results in blocks to never get ChainLocked until 6 confirmations when just a single unsafe TX is included. It also makes the whole tracking of firstSeenTime/firstSeenHeight unnecessary, as every TX in a new block has 1 confirmation, no matter when it was seen first.
The idea with the firstSeen time-tracking was that individual nodes would consider a TX safe after not seeing a conflicting IS lock for X minutes. True, the result is that individual nodes will consider TXs to be safe at different times, but this is ok. In that case, one node after another will sign the block, resulting in the signing session to not timeout until no new sig share appears for one minute or after a total of 5 minutes. So, even if nodes sign at different times, the CLSIG should be created eventually.

It also makes the whole tracking of firstSeenTime/firstSeenHeight unnecessary, as every TX in a new block has 1 confirmation, no matter when it was seen first.

It still tracks txes from mempool which are not mined in next few blocks. I think I see where confusion is coming from, new commits should make it a bit clearer I hope and also fix a potential race condition between TrySignChainTip/IsTxSafeForMining and Cleanup (which also exists in current code btw but is less obvious).

Ah ok, now I understand better. But this still leaves us with the problem that a freshly received block that contains a fresh unsafe TX will result in CLs not being signed for the next 4 blocks, no matter how much time passed since the block with the unsafe TX appeared.
In the current solution, if a TX appears in a block that is unknown, signing of CLs will continue after the timeout. So lets say block 5 had an unsafe TX, so no CLSIG. Then block 6 appears after 2.5 minutes, still no CLSIG (for none of the blocks). Then after some time, 7 and 8 appear and total time passed since block 5 reaches 10 minutes (or whatever timeout we choose later), now the current tip is considered safe immediately and all nodes sign the CL, even if block 5 did not reach 6 confirmations yet.
Maybe a hybrid solution works better? We track the block height at which the TX was seen first and then use that blocks time as basis to determine if a TX is known long enough until we consider it safe. Or we track the time of the block where the TX appeared to make things easier.

In the current solution... and total time passed since block 5 reaches 10 minutes (or whatever timeout we choose later)

The problem is that by that time node might receive 6 (fast) blocks already and cleanup could wipe tx out of "seen" map and thus txAge will always be 0 (i.e. tx will always be "unsafe"). The issue is a fundamental difference between the expected/real time and actual blocks which is basically in the nature of the mining. With this PR the only "time" is blocks, so to say.

Maybe a hybrid solution works better? We track the block height at which the TX was seen first and then use that blocks time as basis to determine if a TX is known long enough until we consider it safe. Or we track the time of the block where the TX appeared to make things easier.

This doesn't solve the issue, see above. Also, can't rely on nTime of the block header (if I understand what you are proposing here correctly), it can vary a lot and miners will be able to trick IsTxSafe... to get their blocks locked even if no txes were seen/locked earlier.

The problem is that by that time node might receive 6 (fast) blocks already and cleanup could wipe tx out of "seen" map and thus txAge will always be 0 (i.e. tx will always be "unsafe"). The issue is a fundamental difference between the expected/real time and actual blocks which is basically in the nature of the mining. With this PR the only "time" is blocks, so to say.
In that case the TX will not be checked if its safe or not and the whole block is then assumed to be safe. Look  at https://github.com/dashpay/dash/pull/2759/files#diff-80dfe69dedcffa54ffef1075c78ada96R275, which bails out from the whole checking. Only the last 6 (including the to be signed tip) blocks are checked here.

@codablock Hmm.. ok, I stand corrected, this works for signing. But it doesn't work for mining (IsTxSafeForMining()) unless I'm missing smth there as well.

For mining, such a TX wouldn't be in the mempool anymore (as it got mined in a rapid chain). Can you maybe describe the original problem you tried to solve?

Nvm, I figured out where I got it all wrong (Cleanup). Thanks :)


vs-version is not working and MSBuild always use latest

Hi,
I am just running one build pipeline for unlimited parts repo with VS2017. But I am facing issues with the wrong selection of the VS version and so build failed. Here is the screenshot.

@Ram-Maersk Is this a hosted agent?

@timheuer No, it is not self hosted. It is GitHub hosted runner. Windows-latest.

Okay that makes sense now. The hosted agents only have latest version of VS on them. The version flag is really there in the event that changes and/or you have self-hosted agents.

@timheuer  Ohh. That looks difficult then if we want to build VS 2017 solution using Github runners as the solution works with VS 2017 only. Do you know any other possibilities?

@Ram-Maersk You can use the windows-2016 image which has VS 2017 installed per https://github.com/actions/virtual-environments/blob/master/images/win/Windows2016-Readme.md and then just omit the version argument here.


Authorization

introduce 3 authorization levels:

read-only : authenticated-user
run actions : role reviewer
all : role processor

Hi @danjoa or @johannes-vogel ,
either something isn't working as expected or I am doing something wrong - could any of you please have a look?
User "alice" has no role assigned -> my assumption is: can only read.
When running locally (cds w) and logging in with "alice", I can do everything (run actions, delete entries ...)
Now, if I comment out the two lines
https://github.com/SAP-samples/cap-sflight/blob/916d0faeff46498a6ae29a4ae38343ee2f848734/srv/travel-service.cds#L14-L15
in the service definition, it works as expected: "alice" can only read.
But - in my understanding - these two lines should have no effect on "alice".
-> ???

Remark: in the current state the test failures are expected.

Hi @danjoa or @johannes-vogel , either something isn't working as expected or I am doing something wrong - could any of you please have a look?
User "alice" has no role assigned -> my assumption is: can only read. When running locally (cds w) and logging in with "alice", I can do everything (run actions, delete entries ...)
Now, if I comment out the two lines
https://github.com/SAP-samples/cap-sflight/blob/916d0faeff46498a6ae29a4ae38343ee2f848734/srv/travel-service.cds#L14-L15
in the service definition, it works as expected: "alice" can only read. But - in my understanding - these two lines should have no effect on "alice". -> ???

alice has the role admin by default. Can you try with an empty roles array?

Hi @johannes-vogel ,
yes, that works, thanks.
So I just made an unfortunate choice of my example users :-) - wasn't aware of these default users

Hi @rjayasinghe ,
there is a little mismatch between nodejs and java concerning authorization. In Java:
testuser "martha" has role "reviewer", which allows to execute actions. "accept travel" and "decline travel" works fine, but when executing "deduct discount", there is an error
Not authorized to send event 'UPDATE' to 'TravelService.Travel'

On nodejs side there is no such error, i.e. role "reviewer" can perform action "deduct discount".
Is this a general diff between java and node backends, or is this due to the implementation of the custom actions (and thus can be fixed in sflight)?

Hi @rjayasinghe , there is a little mismatch between nodejs and java concerning authorization. In Java: testuser "martha" has role "reviewer", which allows to execute actions. "accept travel" and "decline travel" works fine, but when executing "deduct discount", there is an error
Not authorized to send event 'UPDATE' to 'TravelService.Travel'

On nodejs side there is no such error, i.e. role "reviewer" can perform action "deduct discount".
Is this a general diff between java and node backends, or is this due to the implementation of the custom actions (and thus can be fixed in sflight)?

In Java the role 'reviewer' can perform the actions but it seems that it has no permissions to UPDATE entities. It's debatable whether an UPDATE triggered from a permitted action is also permitted. I'll check with the CAP Java team.

In Java the role 'reviewer' can perform the actions but it seems that it has no permissions to UPDATE entities. It's debatable whether an UPDATE triggered from a permitted action is also permitted.

My opinion is: if I am authorized to perform an action, then I should not need additional authorization for really being able to use the action.
And: I can perform the "acceptTravel" and "declineTravel", which also perform an UPDATE on Travel -> they change the status

And: I can perform the "acceptTravel" and "declineTravel", which also perform an UPDATE on Travel -> they change the status

That's true. Let's see what the experts say. :)

@stewsk as always, the differences are subtle: In CAP Java the authorization for DB access is checked only when the statement is accessed on service level (via an instance of ApplicationService). If the access happens on DB level (via an instance of PersistenceService) no additional authorization checks are performed. In our case the DeductDiscountHandler always uses the the DraftService as it needs to be draft-aware. The DraftService is also an ApplicationService. So with this call
https://github.com/SAP-samples/cap-sflight/blob/c1fc4b5c77f9b370aac9344018f3b4286d1ed164/srv/src/main/java/com/sap/cap/sflight/processor/DeductDiscountHandler.java#L56 the calling user needs UPDATE privileges on the entity Travel.
In https://github.com/SAP-samples/cap-sflight/blob/main/srv/src/main/java/com/sap/cap/sflight/processor/AcceptRejectHandler.java#L81-L90
you can see that in case of draft-enabled handling we use a DraftService instance for the UPDATE and in the non-draft case we use a PersistenceService that does not perform authorization checks. TBH I cannot tell anymore why I did not choose an ApplicationService instance for the non-draft case. This would have been more consistent.
In summary: at least from the CAP Java perspective it would be correct if the reviewer role had also UPDATE privileges on the Travel entity. Alternatively, the statement could also be executed in the context of a more privileged user.
@johannes-vogel is there such a differentiation (regarding authorization in DB and service layer) in CAP node.js?

@johannes-vogel is there such a differentiation (regarding authorization in DB and service layer) in CAP node.js?

Yes, that differentiation is also done in node.js.
The update is done on DB layer without authorization checks:
https://github.com/SAP-samples/cap-sflight/blob/c1fc4b5c77f9b370aac9344018f3b4286d1ed164/srv/travel-service.js#L130-L136

But if role "reviewer" had also UPDATE auth for Travel, he could change all sorts of stuff, that is not intended. I also want him to be able to perform the action.
Is there a way to write the handler in such a way that no additional UPDATE auth is needed?

In that case we'd need to define a suitable request context that would allow an UPDATE on the Travel entity. I could try to contribute the needed changes to this PR.

That would be cool

@stewsk I pushed a changed version of the custom handlers for deduct discount and accept/reject but I could not really validate if it works now. Please have a look.

@stewsk I now worked with the fixed credentials for 'martha' and I was able to call decuctDiscount and accept/rejectTravel without issues. Issue seems to be fixed, right?

Deployment works as well 👍, see URL above
The deploy script assigned all of us the admin role, in case you wonder.


update flutter_hooks version

Because every version of osm_flutter_hooks depends on flutter_hooks ^0.18.5+1 and app_package depends on flutter_hooks ^0.20.3, osm_flutter_hooks is forbidden.
i think its time update flutter_hooks version

yeah true i will update the dependencies

its done


Can we have user-type-dependent functions?

We need somewhere that specifies the actions that an user-type can do. For the navbar...
where can we put this?

@rang1 @rvabhishek


Multiple App versions

Some apps, for example MyInsta, provide multiple versions of the app. Clone and Unclone in MyInsta's case. This app downloads only the Unclone version. It would be nice if the user could choose between thise versions.
Thanks for this cool app btw 🔥

Same, for instander the app downloads cloned version not the original ver.

Done 🤌


Non-KNative Resource Option

We want to allow the user to run kfserving components without the dependency on KNative.
An initial implementation could :

Allow non-knative option via annotations
Create raw k8s deployments and services for model serving components.

I suggest listing the feature in a high priority. We (Caicloud) have an internal version of Serving CRD, which is based on Kubernetes Ingress/Service and Istio. I think we should support different serving backends to be more general.
How about define an interface for serving backends and use annotations or CLI flags in controller to control what backends (KNative, Istio, Linkerd, Kubernetes Native Ingress/Service) will be used

/kind feature

we actually discussed about the annotation approach in our WG meeting today.

@gaocegege  That sounds good. To handle canaries and blue/green routing the annotation would indeed need to specify the routing resources to utilize:

KNative (default?)
Istio
Linkerd
Envoy

@cliveseldon KNative by default SGTM. Using Kubernetes native resources to handle canaries and blue/green routing may be hard, while it is feasible to use istio/linkerd/knative. Thus the list LGTM.
@yuzisun Is there any calendar for the SIG meeting? I am interested in it, too.

@gaocegege, I've added you to the meetings.

I want to minimize the number of implementations. I'm all for pluggability, but we need to make sure we're delivering clear customer value. Knative itself is working on the pluggability question, so we may be able to simply rely on their improvements.
Short term, as we discussed in our KFSWG meeting, the best value for effort will be:

Default Knative impl w/ canarying & all the bells
Annotated raw k8s impl w/o canarying

Also @gaocegege, in our discussions so far, we've limited the networking responsibilities of KFServing to in-cluster communication. If you have Knative/Istio installed, you can use their Loadbalancer Service for Ingress, but we're not providing an Ingress solution ourselves.
I'm not sure we want to be creating ingress resources, as they don't map 1:1 with a KFService. If there's some disagreement here, this might be a great topic for a KFSWG Special Topics meeting.

To clarify, what does ingress resource include? I assume you mean any setup of ingress load balancers, external IP etc. right? I also assume it doesn't include ingress rules. In #6 we discussed an internal and external URL as part of the status field... I assumed to get an external URL the implementation would have to write some sort of implementation specific ingress rule?

I think having raw k8s resources (svcs,deployments) created only makes sense if the whole spec for kfserving can be satisfied. If canaries, blue/green, scaling can't be handled then the spec is broken for people who don't want to use KNative.
Just looking at istio, it seems they don't have Go types yet. See here. KNative uses their own versions which is probably ok to reuse for now.
We should decide to either make this issue a

Non-goal and make the top level README clear this is a KNative only implementation
Leave for later incorporation
Handle full functionality which might need to include istio, linkerd as well as HPAs for autoscaling.

It is still a bit unclear to me for the value of implementing the spec with istio, correct me if I am wrong:

to have canary rollout you need to create istio virtual service, setup istio networking and have some way to clean up the deployments like knative revision gc. Not sure if it is worth the effort to implement exactly what knative serving has done.
knative serving is pretty lightweight and you get auto scaling down to zero for free.
future integration with kf pipeline would probabily need knative eventing

@yuzisun Teah knative is built on top of istio and has a higher level abstraction, while in China, AFAIK, there are few companies running knative in production environment. They may have istio installed but they do not use knative. Then they cannot use our Serving CRD.
I the early stage, I agree that we could focus on knative implementation, while I hope that we could keep extensibility to support more backends to satisfy the request of the majority applications

Agreed @gaocegege . Given how young this project is, I see multiple implementations and pluggability as much lower priority. When we do consider where and how we make this system pluggable, we need to be really thoughtful about what value we're delivering (unless of course, someone wants to provide the resources themselves).
Knative is in Beta and growing massively. I could imagine that in a year it will be as standard as Istio, so we wouldn't necessarily want to spend too much effort. Let's make the core functionality available and see where the customer gaps are and address them then.

SGTM. thanks.

Given the direction of this project, its growing featureset, and our impending reliance on eventing. I'm closing this as a non-starter.


Add badges and update Chinese README

Enhance the README with visually appealing badges and update the Chinese version for better accessibility.

Thank you! looks nicer indeed


TEXT-156: Fix the RegexTokenizer to use a static Pattern.

Use of a static pattern avoids the compile step on each invocation.
Remove the use of CharSequence.toString() to pass to the
matcher(CharSequence) method. The String conversion is not needed.
Fix the javadoc header @code tag.

+1
Travis-CI is unhappy with a constant name I think

ERROR] src/main/java/org/apache/commons/text/similarity/RegexTokenizer.java:[36,34] (naming) ConstantName: Name 'pattern' must match pattern '^[A-Z][A-Z0-9](_[A-Z0-9]+)$'.

Funny, job for "JDK: openjdk-ea Java" failed. So just kicked it again. But it passed on 8, 11, and 12. So not a blocker IMO.

I think it's only Travis having a network hiccup @aherbert . Feel free to do the honours if you'd like and merge/update changes.xml/jira 🙂 and thanks for the PR!


Install fails with Error: Cannot find module '../cordova/platform_metadata'

Installing on Ionic results in a failure with:

Saved plugin info for "cordova-plugin-qrscanner" to config.xml
(node:2518) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Cannot find module '../cordova/platform_metadata'

There were similar errors with cordova-plugin-ios etc that are supposed to have been fixed and may show the error.
Workaround is to downgrade from Cordova 8 to cordova 7.1.0
npm uninstall -g cordova
npm install -g<EMAIL_ADDRESS>and then installed with cordova...  not ionic cordova.
My env when I first encountered the error:
ionic info
cli packages: (/Users/joelm/.nvm/versions/node/v8.4.0/lib/node_modules)
@ionic/cli-utils  : 1.19.1
ionic (Ionic CLI) : 3.19.1

global packages:
cordova (Cordova CLI) : 8.0.0

local packages:
@ionic/app-scripts : 3.1.8
Cordova Platforms  : android 7.0.0 ios 4.5.4
Ionic Framework    : ionic-angular 3.9.2

System:
Android SDK Tools : 26.0.2
ios-deploy        : 1.9.2
ios-sim           : 6.1.2
Node              : v8.4.0
npm               : 5.6.0
OS                : macOS High Sierra
Xcode             : Xcode 9.2 Build version 9C40b

Environment Variables:
ANDROID_HOME : /Users/joelm/Library/Android/SDK

Misc:
backend : pro

same issue please help

Same issue here !!

Same Problem :(

Step 1: delete all folder except src and resources
Step 2: run command  npm install
Step 3: run command ionic serve
Step 4: run command ionic cordova build android
this process solved my issue

I couldn't fix it and now I'm using the Barcode Scanner. This plugin can also scan QR codes.

I have the same error, and I do not use ionic.
Command:
phonegap plugin add cordova-plugin-qrscanner
Error:
(node:14296) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Cannot find module '../cordova/platform_metadata'
Is there a fix or workaround available?

I've been encountering that same issue...

My solution: use phonegap-plugin-barcodescanner. Although I understand that might not be possible for everyone.

My solution: use phonegap-plugin-barcodescanner. Although I understand that might not be possible for everyone.

I wanted to try this plugin, since the phonegap-plugin-barcodescanner plugin is a bit slow in opening the scanner.

Yes, the phonegap scanner is definately a bit slower. But what can one do :(

Yeah indeed. I had implemented Scandit which is superior over all scanners, but it's way to expensive also.

As a workaround, you can downgrade to cordova 7:
 npm uninstall -g cordova && npm install -g<EMAIL_ADDRESS>

I have the same issue

I have the same issue

I got it to work eventually.
I just kept removing the platforms and node_modules. Added the platforms and did an npm install again.
I think i also added "cordova-plugin-add-swift-support" to package.json with version number "^1.7.2".

try this
This was a bug in cordova-plugin-add-swift-support, just update it to latest version (1.7.1)
cordova plugin rm cordova-plugin-add-swift-support --force
cordova plugin add cordova-plugin-add-swift-support
credit : https://stackoverflow.com/questions/48087357/cordova-8-ios-4-5-4-cannot-find-module-cordova-platform-metadata

Fixed in 2.6.0 🚀