eXpand icon indicating copy to clipboard operation
eXpand copied to clipboard

JobScheduler.Hangfire Application Error opening Dashboard

Open ricardoamm opened this issue 1 year ago • 26 comments

In development mode, when I select a Worker and open dashboard i got the following error, but the dashboard is opened in new tab. In production, the dashboard is not opened,

The error occurred:

Type:       JSException
Message:    Converting circular structure to JSON
--> starting at object with constructor 'Window'
--- property 'window' closes the circle

TypeError: Converting circular structure to JSON --> starting at object with constructor 'Window' --- property 'window' closes the circle at JSON.stringify () at D (https://localhost:5003/_framework/blazor.server.js:1:5345) at https://localhost:5003/_framework/blazor.server.js:1:3541 Data: 0 entries Stack trace:

at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args) InnerException is null

ricardoamm avatar Nov 17 '23 12:11 ricardoamm

please post a sample and details on how to repro this

apobekiaris avatar Nov 24 '23 18:11 apobekiaris

Hi, I just select one worker from job and then click on the Dashboard button. record.zip

ricardoamm avatar Jan 29 '24 22:01 ricardoamm

The issues seems related to invocation "JsRuntime.InvokeAsync(" instead "JsRuntime.InvokeVoidAsync("

ricardoamm avatar Jan 30 '24 11:01 ricardoamm

did you tried to upgrade the hangfire libs to a newer version to see if they resolved it?

apobekiaris avatar Jan 30 '24 11:01 apobekiaris

I found the problem in your code on the class Xpand.XAF.Modules.JobScheduler.Hangfire.JobSchedulerService, method JobDashboard.

The return code, should be:

return args.SelectedObjects.Cast<JobWorker>().ToObservable(ImmediateScheduler.Instance) .Select(job => jsRuntime?.InvokeVoidAsync("open", $"{uri}{job.Id}", "_blank").AsTask());

Could you confirm, please? It worked for me, but I prefer to reference the Nuggets.

ricardoamm avatar Jan 30 '24 15:01 ricardoamm

I recently switched the JobScheduler tests to integration tests, for testing the actual app instead of a SUT system, however yet no test for Dashboard. I will add one when my time permits for now your observation looks correct, I will update the source code.

Feel free to send a PR when ever u have any fix that was a nice catch

apobekiaris avatar Jan 30 '24 16:01 apobekiaris

I do not see how it worked for you as it does not even compile unless you posted a wronf snippet. Without testing the correct version should be

args.SelectedObjects.Cast<JobWorker>().ToNowObservable()
                        .SelectMany(job => Observable.FromAsync(() => jsRuntime?.InvokeVoidAsync("open", [$"{uri}{job.Id}", "_blank"]).AsTask()))

can u please test is fine so I can send a build?

apobekiaris avatar Jan 30 '24 16:01 apobekiaris

Should be Select instead SelectMany, SelectMany is for relations n to n, which is not the case :

return args.SelectedObjects.Cast<JobWorker>().ToObservable(ImmediateScheduler.Instance).Select(job => jsRuntime?.InvokeVoidAsync("open", $"{uri}{job.Id}", "_blank").AsTask());

ricardoamm avatar Jan 30 '24 16:01 ricardoamm

your answer beats me, can you explain why you think the Task should not be flattened?

apobekiaris avatar Jan 30 '24 16:01 apobekiaris

The SelectMany is the operator that flattens the inner observable which in this case is the task. Although this task is executed on creation so it worked as you mentioned with the Select is not the correct approach and probably the ToUnit hide it from you.

IObservable<IObservable<Unit>> observable = e.SelectedObjects.Cast<JobWorker>().ToNowObservable()
                        .Select(job => jsRuntime?.InvokeVoidAsync("open", [$"{uri}{job.Id}", "_blank"]).AsTask().ToObservable());

the Select will project the Task to IObservable<IObservable<Unit>> where the SelectMany will flatten it

IObservable<Unit> observable = e.SelectedObjects.Cast<JobWorker>().ToNowObservable()
                        .SelectMany(job => jsRuntime?.InvokeVoidAsync("open", [$"{uri}{job.Id}", "_blank"]).AsTask().ToObservable());

apobekiaris avatar Jan 30 '24 17:01 apobekiaris

Ok, maybe I'm not seeing the whole concept here. I'm used to LINQ and I use SelectMany() to collapse a multidimensional sequence in a way that would otherwise require a second Select() or loop. In this case, i thought we just want to select the JobWorker Id's in a simple one-to-one projection, and foreach one create create a task.

ricardoamm avatar Jan 30 '24 17:01 ricardoamm

I use SelectMany() to collapse a multidimensional sequence

it is LINQ and it is as you said it now else flattening and our return is a Unit not a worker. A Unit is a type we use to merge all observables into a signle subscription

   .Merge(manager.TriggerJobsFromAction())
                    .Merge(manager.PauseJobsFromAction())
                    .Merge(manager.ResumeJobsFromAction())
                    .Merge(manager.JobDashboard())

all this methods same for LINQ must have the same type in order to operate on them (Merge, Concat etc) so we use the Unit, the ToUnit method is a convenient extension that projects any type however if you not carefull it hides the whole picture from you

public static IObservable<Unit> ToUnit<T>(this IObservable<T> source) 
            => source.Select(_ => Unit.Default);

apobekiaris avatar Jan 30 '24 17:01 apobekiaris

Ok, thanks for the clarification. What is the expected behaviour, o new dashboard tab shoud be opened for each selected Worker? I selected multiple Workers, but only one tab is opened.

ricardoamm avatar Jan 30 '24 17:01 ricardoamm

The pre-release 4.232.2.0 in the Reactive.XAF lab branch includes commits that relate to this task:

  • [JobScheduler.Hangfire Application Error opening Dashboard

#1028](https://github.com/eXpandFramework/Reactive.XAF/commit/663345a48fec111b62b6a6649ddb504c3646acdc)

To minimize version conflicts we recommend that you use the Xpand.XAF.Core.All, Xpand.XAF.Win.All, Xpand.XAF.Web.All packages. Doing so, all packages will be at your disposal and .NET will add a dependecy only to those packages that you actually use and not to all (see the Modules installation-registrations youtube video).

Released packages: Xpand.Extensions v.4.232.2 Xpand.Extensions.Blazor v.4.232.2 Xpand.Extensions.Mono.Cecil v.4.232.2 Xpand.Extensions.Office.Cloud v.4.232.2 Xpand.Extensions.Office.Cloud.Google.Blazor v.4.232.2 Xpand.Extensions.Reactive v.4.232.2 Xpand.Extensions.XAF v.4.232.2 Xpand.Extensions.XAF.Xpo v.4.232.2 Xpand.TestsLib v.4.232.2 Xpand.TestsLib.Blazor v.4.232.2 Xpand.TestsLib.Common v.4.232.2 Xpand.TestsLib.EasyTest v.4.232.2 Xpand.VersionConverter v.4.232.2 Xpand.XAF.Core.All v.4.232.2 Xpand.XAF.Modules.AutoCommit v.4.232.2 Xpand.XAF.Modules.Blazor v.4.232.2 Xpand.XAF.Modules.BulkObjectUpdate v.4.232.2 Xpand.XAF.Modules.CloneMemberValue v.4.232.2 Xpand.XAF.Modules.CloneModelView v.4.232.2 Xpand.XAF.Modules.Email v.4.232.2 Xpand.XAF.Modules.GridListEditor v.4.232.2 Xpand.XAF.Modules.HideToolBar v.4.232.2 Xpand.XAF.Modules.JobScheduler.Hangfire v.4.232.2 Xpand.XAF.Modules.JobScheduler.Notification v.4.232.2 Xpand.XAF.Modules.MasterDetail v.4.232.2 Xpand.XAF.Modules.ModelMapper v.4.232.2 Xpand.XAF.Modules.ModelViewInheritance v.4.232.2 Xpand.XAF.Modules.Office.Cloud.Google v.4.232.2 Xpand.XAF.Modules.Office.Cloud.Google.Calendar v.4.232.2 Xpand.XAF.Modules.Office.Cloud.Google.Tasks v.4.232.2 Xpand.XAF.Modules.Office.DocumentStyleManager v.4.232.2 Xpand.XAF.Modules.OneView v.4.232.2 Xpand.XAF.Modules.PositionInListView v.4.232.2 Xpand.XAF.Modules.ProgressBarViewItem v.4.232.2 Xpand.XAF.Modules.RazorView v.4.232.2 Xpand.XAF.Modules.Reactive v.4.232.2 Xpand.XAF.Modules.Reactive.Logger v.4.232.2 Xpand.XAF.Modules.Reactive.Logger.Client.Win v.4.232.2 Xpand.XAF.Modules.Reactive.Logger.Hub v.4.232.2 Xpand.XAF.Modules.Reactive.Rest v.4.232.2 Xpand.XAF.Modules.RefreshView v.4.232.2 Xpand.XAF.Modules.SequenceGenerator v.4.232.2 Xpand.XAF.Modules.Speech v.4.232.2 Xpand.XAF.Modules.SpellChecker v.4.232.2 Xpand.XAF.Modules.StoreToDisk v.4.232.2 Xpand.XAF.Modules.SuppressConfirmation v.4.232.2 Xpand.XAF.Modules.TenantManager v.4.232.2 Xpand.XAF.Modules.ViewEditMode v.4.232.2 Xpand.XAF.Modules.ViewItemValue v.4.232.2 Xpand.XAF.Modules.ViewWizard v.4.232.2 Xpand.XAF.Modules.Windows v.4.232.2 Xpand.XAF.Web.All v.4.232.2 Xpand.XAF.Win.All v.4.232.2

Please update the related Nuget packages and test if issues is addressed. These are nightly nuget packages available only from our NugetServer.

If you do not use these packages directly but through a module of the main eXpandFramework project, please wait for the bot to notify you again when integration is finished or update the related packages manually.

Thanks a lot for your contribution.

apobekiaris avatar Jan 30 '24 17:01 apobekiaris

from the RX side we expect a task for each selected object to run

jsRuntime?.InvokeVoidAsync("open", [$"{uri}{job.Id}", "_blank"]).AsTask().ToObservable()

apobekiaris avatar Jan 30 '24 17:01 apobekiaris

if u want to debug i suggest u verify if they open one by one so to have 2 tabs open at the end, so is it the browser that does not allow multiple popups in very close interval? then maybe a StepInterval operator can help and so on..

apobekiaris avatar Jan 30 '24 17:01 apobekiaris

or a SelectManySequential operator instead of SelectMany to flatten the task

apobekiaris avatar Jan 30 '24 18:01 apobekiaris

Thank you very much. When new nuggets will be released?

ricardoamm avatar Jan 31 '24 09:01 ricardoamm

nugets are already in the lab server, aren't they good enough at least for testing?

apobekiaris avatar Jan 31 '24 09:01 apobekiaris

sure, I need to add a new package souce to reference them?

ricardoamm avatar Jan 31 '24 09:01 ricardoamm

strange you can recompile/modify the source and you not aware of the readme? :)

image

did you by any chance find the time to experiement with my last suggestions? SelectManySequential + StepInterval

apobekiaris avatar Jan 31 '24 09:01 apobekiaris

The browser was blocking multiple popups, so it's ok as it is. I don't know how to specify the stepinterval, but the SelectManySequential also works.

ricardoamm avatar Jan 31 '24 10:01 ricardoamm

I'm using Hangfire because Windows Workflow Foundation is no longer supported in the new . NET 8. What is the purpose of the JobScheduler Notification Module?

ricardoamm avatar Jan 31 '24 10:01 ricardoamm

do u mean that it does not work with SelectMany but works with the SelectManaySequential?

apobekiaris avatar Jan 31 '24 10:01 apobekiaris

work in both ways

ricardoamm avatar Jan 31 '24 10:01 ricardoamm

return e.SelectedObjects.Cast<JobWorker>().ToNowObservable()
                        .StepInterval(1.Seconds())
                        .SelectManySequential(job => jsRuntime?.InvokeVoidAsync("open", [$"{uri}{job.Id}", "_blank"]).AsTask().ToObservable());

you can add StepInterval just b4 the inner observable what that means is that it will wait for 1 second then it will open the page and it will wait for the task to complete (that's why we flatten) b4 moving to the next item

apobekiaris avatar Jan 31 '24 10:01 apobekiaris

Closing issue for age. Feel free to reopen it at any time.

.Thank you for your contribution.

expand avatar Apr 27 '24 21:04 expand