Doctrine loadClassMetadata - doctrine-orm

Strange problem.
I have an entity which has property set up by Doctrine loadClassMetadata:
App\EventListener\DrinkEventListener:
arguments:
- { drinkImagesWebPath: '%env(DRINK_IMAGE_WEB_PATH)%', appUrl: '%env(APP_URL)%' }
tags:
- { name: doctrine.event_listener, event: loadClassMetadata }
I changed argument to normal parameter ('%app_url%'), no luck.
DrinkEventListener:
...
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
Drink::$appUrl = $this->appUrl;
Drink::$drinkImageWebPath = $this->drinkImagesWebPath;
}
The problem is, when I clear Symfony cache with warmup, then these properties are empty. Event handler is executed though.
When I clear cache with no-warmup, these properties exist.

Related

How to setup EventHub disasterRecoveryConfigs using Azure bicep?

I have created a module 'resources.bicep' to create event hub namespace in two regions.
resource eventHubNamespace 'Microsoft.EventHub/namespaces#2021-11-01' = {
name: resourceName
location: location
sku: {
name:'Standard'
tier:'Standard'
capacity:1
}
}
resource eventHub 'Microsoft.EventHub/namespaces/eventhubs#2021-11-01' = if (shortRegion == 'wus2') {
name: 'city-temprature'
parent: eventHubNamespace
properties: {
messageRetentionInDays: 1
partitionCount: 2
}
}
From the parent bicep file I run the module as
module weatherWest 'resources.bicep' = {
name:'westResources'
scope:resourceGroup('${name}-wus2')
params: {
name: name
shortRegion: 'wus2'
location: 'westus2'
}
}
module weatherEast 'resources.bicep' = {
name:'eastResources'
scope:resourceGroup('${name}-eus2')
params: {
name: name
shortRegion: 'eus2'
location: 'eastus2'
}
}
How do I setup the GeoPairing?
I have not found a way to call Microsoft.EventHub/namespaces/disasterRecoveryConfigs#2021-11-01 from the parent bicep file.
Code is located in this branch
https://github.com/xavierjohn/SearchIndexDisasterRecoverNearRealTime/blob/bicep/bicep/weatherResources.bicep
Per the docs,
you need to specify a parent resource. You can look up an existing resource with the existing keyword.
Something along these lines should work.
resource primary 'Microsoft.EventHub/namespaces#2021-11-01' existing = {
name: 'primaryEventHubName'
resource secondary 'Microsoft.EventHub/namespaces#2021-11-01' existing = {
name: 'secondaryEventHubName'
resource symbolicname 'Microsoft.EventHub/namespaces/disasterRecoveryConfigs#2021-11-01' = {
name: 'foo'
parent: primary
properties: {
alternateName: 'string'
partnerNamespace: secondary.id
}
}
I got help from the Azure Bicep team and currently there is no way to pass a resource as output but they are working on a proposal. For now there is a trick that will work so till the elegant solution comes out,
use existing and set dependsOn on the Geo Pairing fragment.
The end code looks like below.
module allResources 'resources.bicep' = [for location in locations : {
name:'allResources'
scope:resourceGroup('${name}-${location.shortRegion}')
params: {
name: name
shortRegion: location.shortRegion
location: location.region
}
}]
resource primaryEventHubNamespace 'Microsoft.EventHub/namespaces#2021-11-01' existing = {
name: '${name}wus2'
}
resource disasterRecoveryConfigs 'Microsoft.EventHub/namespaces/disasterRecoveryConfigs#2021-11-01' = {
name: name
parent: primaryEventHubNamespace
properties: {
partnerNamespace: resourceId('${name}-eus2', 'Microsoft.EventHub/namespaces', '${name}eus2')
}
dependsOn: [
allResources
]
}

ApolloGraphQL: useSubscription Hook Syntax with onSubscriptionData?

I'm trying to build an Apollo useSubscription hook that uses onSubscriptionData.
I've looked in the Apollo docs, but I haven't yet an example.
E.g. something like:
const { loading, error, data } = useSubscription(
INCOMING_MESSAGES_SUBSCRIPTION_QUERY,
{
variables: {"localUserId": Meteor.userId()},
onSubscriptionData: myFunctionThatRunsWhenSubscriptionDataArrives
}
);
That can't be right yet, because it doesn't include OnSubscriptionDataOptions<TData>, which is mentioned in the Apollo docs.
What is the correct way to build a useSubscription hook that uses onSubscriptionData?
The onSubscriptionData function is passed a single options parameter of the type OnSubscriptionDataOptions. The options object has two properties:
client -- the ApolloClient instance used to query the server
subscriptionData -- an object with the following properties: loading, data, error
Example usage:
const { loading, error, data } = useSubscription(
INCOMING_MESSAGES_SUBSCRIPTION_QUERY,
{
variables: {"localUserId": Meteor.userId()},
onSubscriptionData: ({ subscriptionData: { data } }) => {
// do something with `data` here
}
},
)

How to get a full list of loopback4 models to evaluate custom decorator metadata at boot time?

I'm currently migrating a loopback3 application to loopback4. I've annotated the properties in my loopback4 models with a custom typescript decorator with some metadata.
How can I get a full list of models and evaluate their metadata at boot time?
I did some experiments with LifeCycleObserver, but did not find a way how to get notified when all models are ready nor get a list of them.
Here is an simplified example of the metadata i want to process. Please note: #propertyAcl is a custom decorator.
export class Model1 extends AuditMixin(SoftdeleteMixin(AbstractEntity)) {
// ...
#property()
#propertyAcl({
'role1': Permission.READ_WRITE,
'role2': Permission.READONLY,
})
myproperty?: string;
// ...
}
I need to configure the external library accesscontrol with the metadata at boot time. The idea is to create property based acls per model.
How can I get a full list of models and evaluate their metadata at boot time?
Overview
Using #loopback/metadata to create a Decorator and define / get the metadata via MetadataInspector.
Create a DecoratorFactory "A"
Create a Context "B"
Overide the mergeWithInherited function in "A", and in this function we store (define) the metadata of the property that you annotated at design time to "B"
Create a Decorator "C" via "A"
Annotate any properties you want with "C"
Get the metadata in "B" at runtime
Step 1 2 3 4
// 1
class A extends PropertyDecoratorFactory<object> {
constructor(key: string, spec: object, options?: DecoratorOptions | undefined) {
super(key, spec, options);
}
// 3
mergeWithInherited(inheritedMetadata: MetadataMap<object>, target: Object, propertyName?: string, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): any {
// define metadata to "B"
MetadataInspector.DesignTimeReflector.defineMetadata(`${target.constructor.name}.${propertyName}`, this.spec, B);
}
}
// 2
export const B = new Context("B.context");
// 4
export function C(spec: object): PropertyDecorator {
return A.createDecorator<object>(
'C.decorator',
spec,
);
}
Step 5
class ModelFoo extends Model {
#property({
type: 'string'
})
p1?: string;
#C({ metadata: "this is ModelFoo" })
#property({
type: 'string'
})
p2?: string;
}
class ModelBar extends Model {
#property({
type: 'string'
})
p1?: string;
#C({ metadata: "this is ModelBar" })
#property({
type: 'string'
})
p2?: string;
}
Step 6
function Test() {
// get all metadata keys in "B"
let keys: string[] = MetadataInspector.DesignTimeReflector.getMetadataKeys(B);
// output >>>> [ 'ModelFoo.p2', 'ModelBar.p2' ]
console.log(keys);
// get metadata with 'ModelFoo.p2' in "B"
let metadata = MetadataInspector.DesignTimeReflector.getMetadata(keys[0], B);
// output >>>> { metadata: 'this is ModelFoo' }
console.log(metadata);
// do somthing...
}

ngxs: How to test dynamic selectors

I followed the official documentation on testing ngxs selectors (https://ngxs.gitbook.io/ngxs/recipes/unit-testing#testing-selectors), however it doesn't cover how to unittest dynamic selectors created with createSelector.
My normal selector just gets the state as an argument so I can easly test it by passing a prepared state and comparing the output.
#Selector()
static nachweise(state: NachweisStateModel) {
return state.nachweise;
}
//Setup state
const state = {...};
//Compare expectations
expect(NachweisState.nachweise(state)).toEqual(...);
My dynamic selector looks like this:
#Selector()
static nachweisById(id: string) {
return createSelector([NachweisState], state => {
return state.nachweise.find(nachweis => nachweis.id === id);
});
}
The only parameter it gets is the id by which it selects, but not the state. The State is automagically passed in by specifying it as the first parameter to createSelector and I don't know how I should test this selector.
It seems that the documentation has been updated:
it('should select requested animal names from state', () => {
const zooState = {
animals: [
{ type: 'zebra', name: 'Andy'},
{ type: 'panda', name: 'Betty'},
{ type: 'zebra', name: 'Crystal'},
{ type: 'panda', name: 'Donny'},
]
};
const value = ZooSelectors.animalNames('zebra')(zooState);
expect(value).toEqual(['Andy', 'Crystal']);
});

Grails: How does that the UPDATE function work?

I got rid of the original UPDATE gsp Grails offers.
I put it in the first row of my list.gsp table and change all the values of the table to g:textfield so they can be edited without going to the save.gsp
But now I'm trying to make it work, and I can't.
I added a update button in the last column of the row, of every row.
When I change the values of the g:textfields and click the update button it tells me
Density #ID updated
but the values do not change.
I think I am doing something wrong with def update in the controller.
Here is the code:
def update = {
log.info "Entering Action ${actionUri}"
def densityInstance = Density.get(params.id)
if (densityInstance) {
if(params?.Rcommodity) {
println "${params.Rcommodity}"
}
if (params.version) {
def version = params.version.toLong()
if (densityInstance.version > version) {
densityInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'density.label', default: 'Density')] as Object[], "Another user has updated this Density while you were editing")
render(view: "list", model: [densityInstance: densityInstance])
return
}
}
densityInstance.properties = params
if (!densityInstance.hasErrors() && densityInstance.save(flush: true)) {
flash.message = "${message(code: 'default.updated.message', args: [message(code: 'density.label', default: 'Density'), densityInstance.id])}"
redirect(action: "list", id: densityInstance.id)
}
else {
redirect(action: "list", id: densityInstance.id)
}
}
else {
flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'density.label', default: 'Density'), params.id])}"
redirect(action: "list")
}
}
The Rcommodity is the name of the textfields created, I put a println to see if the value was right, now I don't know how to make the value of the textfield be the one entered, it gives me the same value it had before but it gives me the message saying that it was updated.
The controller is DensityController and the domain is density
Any help would be greatly appreciated. Thanks :D
Looks from the flash message being printed as though the instance is being updated (though the "#ID" bit looks odd - have you replaced the actual id?).
It might be that
densityInstance.properties = params
is not actually be matching any instance properties, so none are actually being changed before the save. Are you sure you've named your gsp input fields to match the names of your Density class fields? Is Rcommodity a property of Density, for example?
Might help to add the form bit of your gsp page, as well as the Density domain class.