But you know when the rule definitions are edited, right? Maybe I'm being obtuse, but I feel like this workflow should solve your use case:
1. On module startup, register all tokens. This is efficient--it just stores a token name -> configuration string mapping in the DB. 2. Your RuleProvider compiles rules on the fly the first time they are requested. 3. Whenever the rule definition changes, you call TokenService.notifyRuleDefinitionChanged. (If you really want you can call this before every rule you evaluate, to force the service to re-request the Rule from your RuleProvider.) Am I missing some reason why this won't work? -Darius On Thu, Sep 1, 2011 at 12:34 PM, Tammy Dugan <[email protected]> wrote: > No we don't because we allow compilation on the fly. > > Tammy > > > On 9/1/2011 12:32 PM, Darius Jazayeri wrote: > > Do you know all the available rules ahead of time, even if you don't > necessarily want to pre-register them? > > Perhaps we could have a lazy rule provider that registers all its tokens > ahead of time, but doesn't compile the rules until they're actually > requested? > > -Darius > > On Thu, Sep 1, 2011 at 11:50 AM, McKee, Steven Jay <[email protected]>wrote: > >> The pre-registration of rules is what we’re currently trying to get away >> from. We basically want our rules to be found and loaded as needed. The >> problem is the rules are executed at the OpenMRS level (created by the Arden >> translator). We can’t directly register rules to our provider from there >> since the provider is down in a module. We need something to call before we >> call eval on a rule to make sure it’s loaded (or it won’t be found): >> >> >> >> Rule 1: >> >> >> /////////////////////////////////////////////////////////////////////////////////////// >> >> Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”, >> parameters); >> >> >> /////////////////////////////////////////////////////////////////////////////////////// >> >> >> >> Rule 1 is calling the “ChicaAgeRule” from within it. We need some >> mechanism to ensure the “ChicaAgeRule” is loaded (and load it if it’s not) >> before we call eval. Since we’re trying to avoid pre-registering all the >> rules, there isn’t a good way to get them loaded. >> >> >> >> One possibility is to have the “getRule” method in a rule provider be dual >> purpose. It can load and possibly register the rule if it’s not currently >> registered. The rule provider would then have to be passed in parameters of >> the eval method. The Arden translator could create something like this: >> >> >> >> Rule 1: >> >> >> /////////////////////////////////////////////////////////////////////////////////////// >> >> RuleProvider ruleProvider = (RuleProvider)parameters.get(“ruleProvider”); >> >> If (ruleProvider != null) { >> >> ruleProvider.getRule(“ChicaAgeRule”); >> >> } >> >> Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”, >> parameters); >> >> >> /////////////////////////////////////////////////////////////////////////////////////// >> >> >> >> This doesn’t seem the best way to do it, but I’m not sure of another way >> since we’re trying to avoid pre-registration. This is basically why we were >> proposing to add a new “loadRule” method to the logicService interface so we >> could AOP around it and load our rules: >> >> >> >> Rule 1: >> >> >> /////////////////////////////////////////////////////////////////////////////////////// >> >> logService.loadRule(“ChicaAgeRule”, false); >> >> Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”, >> parameters); >> >> >> /////////////////////////////////////////////////////////////////////////////////////// >> >> >> >> >> >> Thanks, >> >> Steve >> >> >> >> >> >> *From:* Darius Jazayeri [mailto:[email protected]] >> *Sent:* Thursday, September 01, 2011 10:22 AM >> *To:* McKee, Steven Jay >> *Cc:* dev; Dugan, Tammy Marie >> >> *Subject:* Re: New LogicService method >> >> >> >> Yes, you could register your static rules in the afterStartup method on a >> RuleProvider. (That's exactly what that method is for.) >> >> >> >> E.g. the handler in the logic module that handles dynamically-defined >> rules in groovy or java does: >> >> /** >> * @seeorg.openmrs.logic.rule.provider.AbstractRuleProvider#afterStartup() >> */ >> @Override >> public void afterStartup() { >> TokenService tokenService = Context.getService(TokenService.class); >> RuleDefinitionService service = >> Context.getService(RuleDefinitionService.class); >> for (RuleDefinition rd : service.getAllRuleDefinitions()) { >> tokenService.registerToken(rd.getName(), this, >> rd.getId().toString()); >> } >> } >> >> Also, do make sure you extend AbstractRuleProvider rather than just >> implementing RuleProvider, in case that interface ends up getting methods >> added later. >> >> >> >> -Darius >> >> >> >> On Thu, Sep 1, 2011 at 8:15 AM, McKee, Steven Jay <[email protected]> >> wrote: >> >> I can see this approach working well for our dynamic class loading: >> >> >> >> 1. The class loader task looks for new classes. >> >> 2. Once found, the rules get registered to our DSS rule provider. >> >> 3. The DSS rule provider would use our compiling classloader to >> locate the file in the “getRule” method. >> >> >> >> We still, however, have the issue of our static rules in some of our >> modules. We want to be able to use these on the fly, so how would be >> initially get these rules registered? Would be have to write some sort of >> task to do this on startup? Is there anything in logic that provides us a >> way of doing this? I noticed there’s an “afterStartup” method in the >> RuleProvider interface. What exactly is this used for? >> >> >> >> Thanks, >> >> Steve >> >> >> >> >> >> *From:* Darius Jazayeri [mailto:[email protected]] >> *Sent:* Wednesday, August 31, 2011 5:34 PM >> *To:* McKee, Steven Jay; dev >> >> >> *Cc:* Dugan, Tammy Marie >> *Subject:* Re: New LogicService method >> >> >> >> Moving this to the developers list. >> >> >> >> The way this is supposed to work is that if you have a rule >> (YourRule.java) and you want it to be accessible as the token "Your Rule", >> then you need to do something like this: >> >> TokenService.registerToken("Your Rule", chicaRuleProvider, >> "InternalUniqueIdOfYourRule"); >> >> >> >> Then when LogicService.getRule("Your Rule") is called, that will delegate >> to: >> >> chicaRuleProvider.getRule("InternalUniqueIdOfYourRule"); >> >> >> >> Presumably you have a RuleProvider in your module already? (Even if you're >> bypassing LanguageHandler, I think RuleProvider is necessary...) >> >> >> >> The logic infrastructure will cache these rules (since they may be >> expensive to compile) so if you want it to forget a cached value, you'd do: >> >> TokenService.notifyRuleDefinitionChanged("Your Rule"); >> >> >> >> It seems like these methods should be sufficient for what you're trying to >> do. >> >> >> >> (Adding a method to LogicService is pretty significant to do, because >> that's a change to the core api, which requires simultaneous releases of new >> versions of 1.6.x, 1.7.x, and 1.8.x, to support the new logic module. It's >> possible that we end up doing this, but it can't happen quickly.) >> >> >> >> -Darius >> >> >> >> On Tue, Aug 30, 2011 at 2:42 PM, McKee, Steven Jay <[email protected]> >> wrote: >> >> We are currently bypassing the dynamic rule code and language handlers. >> We need the ability to load rules on the fly instead of pre-loading them. >> It just gives us a lot of flexibility and the benefit of not loading rules >> we may not use. >> >> >> >> Thanks, Darius. >> >> >> >> Steve >> >> >> >> *From:* Darius Jazayeri [mailto:[email protected]] >> *Sent:* Tuesday, August 30, 2011 2:04 PM >> *To:* McKee, Steven Jay >> *Cc:* Dugan, Tammy Marie >> *Subject:* Re: New LogicService method >> >> >> >> Hi steve >> >> I'm out and about at the moment, but will try to reply on the dev list >> today out tomorrow. >> >> Isn't there already a workflow so your rule provider can update loaded >> rules though? Or have you ended up bypassing the dynamic rule code and >> language handlers I put in? >> >> -Darius (by phone) >> >> On Aug 30, 2011 1:17 PM, "McKee, Steven Jay" <[email protected]> wrote: >> >> Darius, >> >> >> >> CHICA is very close to finishing the upgrade to OpenMRS 1.7.x, but we’re >> needing an additional method added to the LogicService interface: >> >> >> >> /** >> >> * Loads a rule into memory so it can be used. It will also update >> the rule *metadata* if >> >> * required. >> >> * >> >> * *@param* token the lookup key ("token") for the rule to be >> loaded. >> >> * *@param* updateRule Whether or not the rule *metadata* needs to >> be updated once loaded. >> >> * *@throws* LogicException if an error occurs loading a rule. >> >> */ >> >> *public* *void* loadRule(String token, boolean updateRule) >> *throws*LogicException; >> >> >> >> CHICA currently has the same method in its DSS module which looks in >> various places to load a rule into memory. We currently have hardcoded >> places in our code to load specific rules before any other rules are >> executed. We want to be able to remove the hardcoded loading of the rules >> so we can be more dynamic about it. >> >> >> >> Here’s what we are proposing to do: >> >> 1. Add the new LogicService method. >> >> 2. Update the Arden parser to create Java calls that execute the >> loadRule method on an inner rule before calling “eval”. >> >> logicService.loadRule("LocationAttributeLookup", false); >> >> Result result = context.eval(patient.getPatientId(), >> "LocationAttributeLookup",parameters); >> >> 3. For the time being the implementation of the loadRule method in >> the logic module will do nothing. >> >> 4. We will set up an AOP call for the method in our DSS module so >> we can call our own loadRule to get the correct rule into memory. >> >> 5. The AOP call is a temporary fix until we can eventually get some >> of our DSS code moved into logic in the future. But we’re very close to our >> upgrade deadline at the moment. >> >> >> >> The “updateRule” parameter for the method is used to tell the code whether >> or not the metadata about the rule should be updated. Most of the time in >> normal operating conditions this will be false. The case where we would >> supply true is when are class loading scheduled task is looking for new >> rules. Once it finds a new rule, we want the newest metadata (and >> registration) for it. >> >> >> >> Thanks, >> >> >> >> Steve McKee >> >> Children’s Health Services Research >> >> Indiana University School of Medicine >> >> Phone: 317-278-9660 >> >> Email: [email protected] >> >> >> >> >> >> >> > > > -- > Tammy Dugan > CHIRDL Technical Lead > Children's Health Services Research > IU School of Medicine > > _________________________________________ To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to [email protected] with "SIGNOFF openmrs-devel-l" in the body (not the subject) of your e-mail. [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

