jrule icon indicating copy to clipboard operation
jrule copied to clipboard

Feature collab: make generated JRule jars a remote repo?

Open mindstorms6 opened this issue 2 years ago • 7 comments

Howdy!

First - thanks for taking on this project. It's way way way easier to build rules in an IDE and use external dependencies- this is awesome.

I had a thought about enhancing the way in which jrule vends the jars (and maybe even the way rules are uploaded) - would you be open to me taking a stab at having JRule spin up maven repo that holds the jars and potentially allows users to upload jars as well?

Basically my goal would be to point gradle / maven at my OpenHAB instance - where it could pick up the rule jars and in some crazy future - we could also publish the assembled rule jars there too.

It could also be useful for versioning rules and things - you tell JRule what version of the published jar to use.

I'm open to giving this a shot - so not asking you to do any more work - but wanted your thoughts first.

Thanks again!

mindstorms6 avatar Sep 16 '22 15:09 mindstorms6

Just spitballing - but maybe something like a dependency on reposilite? Might be an easy win (though, I'm certain there are other options)

mindstorms6 avatar Sep 16 '22 18:09 mindstorms6

Java developers will often have their own existing infrastructure set up for their projects. Every developer will have their own preferred development and deployment stack and these will differ from one person to the next. For example I use Reposilite, Laminar, Gitolite, Traefik, Let's Encrypt, Bacula, Darkhttpd (Arch Linux output packages), WireGuard, UFW, Ansible etc.

Irrespective of whichever infrastructure is used, there is an initial and ongoing cost to achieving secure, reliable and consistent integration. Nevertheless such costs are worthwhile when amortised over all available projects. It would therefore be desirable in the case of JRule for any existing infrastructure to be usable.

I do not have any particular view on how to use existing infrastructure other than suggest the simplest thing that could possibly work would be to define some simple contracts around the existing input and output JARs. For example if JRule detects a file system change at /etc/automation/jrule/rules-jar/ it would immediately undeploy any removed JAR and/or redeploy any modified JAR. Similarly JRule would guarantee to never rewrite the jrule-items.jar unless there has been an actual change to the available items. The latter would allow a systemd timer (or a long-running script using inotify-tools or similar) to detect a new version and upload it somewhere using whatever GAV coordinates make sense.

The benefit of this would be minimal changes within JRule while still allowing it to "play nicely" with external infrastructure. It would also fail gracefully, in that if the build infrastructure is unavailable the JARs already in openHAB would continue to operate. Fault tolerance is a major priority for home automation (especially for people who have replaced all their light switches with PoE wall tablets!)

benalexau avatar Sep 17 '22 04:09 benalexau

Nice to see the interest in this. Already today there are mechanisms in place for detecting changes to rules or items and the reload JRule. I would be fairly simple to extend that to include the external jars as well, so whenever an external jar is changed (removed, modified, added) it would reload jrule.

If you have a way to publish jars I think it is fine and we could make changes to JRule to be more "compatible" in that sense. We could also set up reference projects that utilize for instance reposilite to publish and maintain the jar (similar to the https://github.com/seaside1/jrule-user ). I agree with @benalexau to support any type of infrastructure to handle versioning and release and dependencies to jar-files.

seaside1 avatar Sep 18 '22 14:09 seaside1

Thanks for the feedback.

My goal was to make the process of fetching the generated jar a bit more idiomatic. I agree, it probably doesn't make sense in some regard the "publishing" of the user rules jar and dependencies - those mechanisms are likely left best as is.

Taking into account the above comments - would it be a useful feature if we made the generated jar accessible via some sort of maven compatible repo? And we leave the publishing alone for now? (It doesn't have to be reposilite - anything that's able to be used as a repo source would do just fine)

mindstorms6 avatar Sep 27 '22 01:09 mindstorms6

Personally I wouldn't use that feature. The generated jar is not worth storing in that sense for me. It can be regenerated easily and I tend to share it by samba or nfs shared drive. The JRule.jar can be added as a dependency using maven and jitpack (See the jrule-user project as a reference).

seaside1 avatar Oct 03 '22 21:10 seaside1

would be fairly simple to extend that to include the external jars as well, so whenever an external jar is changed (removed, modified, added) it would reload jrule.

This would be useful as there's a precedent in the form of the .java rule files, and supporting this for compiled JARs would allow people to push the replacement rules JARs into openHAB from whatever build automation they use.

The generated jar is not worth storing in that sense for me. It can be regenerated easily and I tend to share it by samba or nfs shared drive.

I agree; there are plenty of ways to get the generated JARs into user projects. The main issue is knowing that the JARs have meaningfully changed and in turn need to be updated in user projects. Simply preventing JRule from rewriting the JARs unless it detects the source content is now different is the most minimal change (eg you could CRC the entire source code stream as code generation progresses and include an entry in the generated manifest for comparison with a future run, thereby not needing any external persistence).

would it be a useful feature if we made the generated jar accessible via some sort of maven compatible repo? And we leave the publishing alone for now?

If generated JARs were only written when their contents changed you would be able to write an external script that basically fetched the existing 1.0.0-SNAPSHOT from your existing Reposilite instance, did a SHA on the fetched items JAR, did a SHA on the current JRule-generated items JAR, and pushed the new items JAR to Reposilite with a 1.0.0-SNAPSHOT version number if they differed. Then your usual infrastructure will pick up the new snapshot on developer machines, CI pipelines and so on.

The script could also fetch 1.0.0-SNAPSHOT of your rules JAR from Reposilite, and if its SHA differed from the current JAR in JRule, overwrite the current rule JAR to trigger JRule to automatically redeploy.

This approach would also be compatible with other mainstream approaches that people probably use, such as Samba shares, FTP or HTTP servers to expose JARs etc. It really just boils down to JRules (a) redeploying the rules JAR if it changes and (b) only rewriting the generated JARs if their source contents have changed. These are pretty minimal changes as far as I can tell and the behaviour of JRule wouldn't be unusual or unpredictable from a user perspective.

benalexau avatar Oct 04 '22 00:10 benalexau

Some good suggestions.

  • Yes would be fairly simple to check the external jars and to a reload when they are changed
  • It would be possible to store a file along side the jrule-items and jrule.jar with checksums or store it in memory to avoid writing the same file multiple times.

Even though it is not a good solution I used to store the jrule-items and jrule.jar in version control and doing that the file will only show as changed / modified if it is actually changed.

seaside1 avatar Oct 04 '22 20:10 seaside1