0

Current application - Angular application with Breeze. Application has ~7 entity managers and different data domains (metadata). When application runs we trying to fetch entity managers, like:

app.run(['$rootScope', 'datacontext1', ... ], function($rootScope, datacontext1, ...) {
   datacontext1.loadMetadata();
...
   datacontext7.loadMetadata();
}

Every datacontext has its own entity manager and loadMetadata is:

function loadMetadata() {
  manager.fetchMetadata().then(function(mdata) {
       if (mdata === 'already fetched') {
          return;
       }
       ...
       applyCustomMetadata(); // Do some custom job with metadata/entity types
  });
}

Metadata comes from server asynchronously. Few module has really big metadata, like 200Kb and takes some time for loading and apply to entity manager. Its possible that first Breeze data request executed in same entity manager will be started before this loadMetadata operation finished and as I understand Breeze automatically fetch metadata again. Usually its not a problem, Metadata end point cached on server, but sometimes it produces very strange behavior of Breeze - EntityManager.fetchMetadata resolve promise as "already fetched" and in this case applyCustomMetadata() operation can not be executed.

As I understand problem is inside Breeze and approach its used to resolve metadata promise (seems to be http adapter is singleton and second request override metadata with "already fetched" string and applyCustomMetadata() operation never executes).

Need to figure out some way to resolve issue without significant changes in application.

Logically need to delay full application from using entity managers while loadMetadata done. Looking for any way on Breeze level to disable auto fetch metadata if its already in progress (but not interrupt request, just wait and try again after some time). Any other ideas are fine as well.

Grigorii
  • 87
  • 1
  • 1
  • 9

1 Answers1

0

Why are you allowing queries to execute before the metadata is loaded? Therein lies your problem.

I have an application bootstrapper that I expose through a global variable; none of my application activities depending on the Entity Manager are started until preliminary processes complete:

var bootstrapper = {
    pageReady: ko.observable(false)
};

initBootstrapper();
return bootstrapper;

function initBootstrapper() {
    window.MyApp.entityManagerProvider.initialize() // load metadata, lookups, etc
        .then(function () {
            window.MyApp.router.initialize(); // setup page routes, home ViewModel, etc
            bootstrapper.pageReady(true); // show homepage
        });
};

Additionally, depending on the frequency of database changes occurring in your organization, you may wish to deliver the metadata to the client synchronously on page_load. See this documentation for further details:

http://breeze.github.io/doc-js/metadata-load-from-script.html

Jonathan
  • 245
  • 1
  • 8
  • Yes, both this ways are options for solving problem, but unfortunately both will affect user experience. First way - blocking start of the application (execute first route) will add 1-2 seconds of user waiting animation (there are 7 entity managers with big metadata). Second - loading metadata synchronously may make application unresponsive for long time (few seconds). Biggest issue - application already in use by many users and solution should not reduce UX, but in same time app was not designed in high scalable way (data domains really too big). – Grigorii Jan 24 '16 at 00:36