Hello, I would very much like this clarified: https://docs.abp.io/en/abp/5.0/Concurrency-Check . Here it says that the concurrency stamp and check is managed by Abp: https://docs.abp.io/en/abp/latest/Entities#basicaggregateroot-class However, I now noticed that, at least in some Abp modules, the concurrency stamp is cycled via UI to update Dtos.
From this https://github.com/abpframework/abp/issues/3351 and from the docs I get the impression that the cycling is not needed but why is it implemented so at least in some modules here for example
My question is that should we always cycle the concurrency stamp through UI or in which cases we should do so.
I have no doupt that saving isn't a problem with this. To be clear, I haven't tried any solution yet, hence the "Design Question". However all the examples I have seen define the extraproperty name staticly and I'm trying to figure out if this king dynamic definition would work as well. If you have some sample code, I will gladly take a look at it :)
Hello, I think the JSON-field will suffice. But the problem isn't that can we map it to another table or not. The problem is that the meaning and value types change will change accross different tenants. For example: Tenant1 needs an additional property "SocialSecurityNumber" which is of type string but Tenant2 doen't care about that information. It needs an additional property "PersonLength" of type integer. We cannot know in advance what additional information each tenant needs, so the properties cannot be defined in advance like in the SetProperty-example. The JSON value would be created dynamically to the database by an external system (an integrator).
We have a situation where we should attatch some extra information to our entites. For example: EntityX has some properties and in addition Tenant1 needs to see extra property "Xyx" and it's value in UI. Tenant2 also needs extra property for EntityX but with different name "Abc" and possibly different value type. These extra properties cannot be determined at build time. At our old solution we just had extra columns for some database tables and meaning of the value was taken care of in customer guidance. I'm looking for more elegant solution than that and was wondering if the Extra Properties -model could provide the solution?
ABP Framework version: v4.4.3 Exception message and stack trace: No exceptions Steps to reproduce the issue: We have Project with Quartz for background workers and a project that contains Background jobs. The jobs are default Abp AsyncBackgroundJobs. With this configuration when ever I enqueue a background job to be excecuted, the excecution is done multiple times if background job excecution time exceeds the background job poll interval. If I unload the project that includes the AbpBackgroundWorkersQuartzModule, the background job is excecuted correctly (only once)
Hello, As it says here https://docs.abp.io/en/abp/latest/Background-Workers-Quartz default Abp background jobs are executed "on top of each other" if they are long running and the job polling interval is shorter. Same job is executed multiple times. This occurs only when Quartz is used with background workers. As the documentation suggests, I added AbpQuartzBackgroundJobs dependency to fix this, but this did not help. Is is so that I cannot use the default background job abstractions in this case and have to use only Quartz's abstractions all the way?
And we should always set the tenant Id as well?
Hello,
this https://docs.abp.io/en/abp/latest/Multi-Tenancy#imultitenant is not very clear on how should we do multitenancy in "Database per tenant" environment.
If we know that we are not going to share our data accross tenants, can we disable multitenancy all together? If not, should only the aggregates be multitenant or entities under aggregates as well?
This came up in a situation where we had both an aggregate and it's entity defined as IMultitenant but our logic only set the aggregate's tenant id in creation. This created a situation where aggregate's GetAsync, sub collection included, never populated the subcollection. Removin the IMultitenant defintion fron the entity fixed this. This got us thinkin do we still need to define aggregates and entities as multitenant if we know that tenant data will always be separated in tenant specific database?
Hi, that won't matter. For some reason the module initalization tries to initialize the scheduler twice if I have two tests. The problem is in the initalization, not in how I get the scheduler in my tests.
Hello, thank you for your answer. I wasn't quite clear on what I was testing. I'm not trying to test the Quarz library, I'm just using it as a tool in my test to assert my logic.
public Ctor(Guid tenantId, string tenantName, string scheduleDefinition)
{
Check.NotNullOrEmpty(tenantName, nameof(tenantName));
Check.NotNullOrEmpty(scheduleDefinition, nameof(scheduleDefinition));
JobDataMap jobDataMap = new()
{
{ "TenantId", tenantId }
};
JobDetail = JobBuilder.Create<ScheduledControlValueCalculationBackgroundWorker>()
.WithIdentity(TenantSpesificBackgoundProcessNameFormat.GetFormattedName(this, tenantName))
.SetJobData(jobDataMap)
.Build();
Trigger = TriggerBuilder.Create()
.WithIdentity(TenantSpesificBackgoundProcessNameFormat.GetFormattedName(this, tenantName))
/*
* Put the schedule to the definition and do the rescheduling based on that info. No other easy way to check
* if the triggers are really the same.
*/
.WithDescription(scheduleDefinition)
.WithCronSchedule(scheduleDefinition, options => options.WithMisfireHandlingInstructionFireAndProceed() )
.Build();
ScheduleJob = async scheduler =>
{
if (!await scheduler.CheckExists(JobDetail.Key))
{
await scheduler.ScheduleJob(JobDetail, Trigger);
}
else
{
// If the job already exists there might be changes to the schedule so reschedule the job if so
IJobDetail jobDetail = await scheduler.GetJobDetail(JobDetail.Key);
var trigger = await scheduler.GetTrigger(Trigger.Key);
if(trigger.Description != Trigger.Description)
{
await scheduler.RescheduleJob(trigger.Key, Trigger);
}
}
};
}