Показаны сообщения с ярлыком Intersystems. Показать все сообщения
Показаны сообщения с ярлыком Intersystems. Показать все сообщения

вторник, 25 ноября 2014 г.

Intersystems Caché - Approaching Community Package Manager - Part II

This is the second part of my long post about package managers in various operating systems and language distributions. Now you probably "buy the idea" that convenient package manager and 3rd party code repository is the key factor in establishing of a live and popular ecosystem. In the second part we will discuss the action plan for creating of a package-manager for the Caché​ database environment.

​So let try to estimate how much we should implement if we would try to add some basic package management facilities to Caché ecosystem? Should we do anything in the kernel, or could it be done as external service? What is the minimum functionality necessary at the beginning to establish anything resembling package management repository? Which still be useful?

Format

1st question to answer - what is composing the “package”? What about simplest ever case - when only Caché classes to be deployed? How we keep multiple file types? In the ideal case – some ZIP container could be used, but in the  simplest case even the simple XML file, as a Caché Studio project export could serve the purpose, because even now we could embed all supported file types (CLS, RTN, INC, CSP, ZEN, CSS, GIF, etc.) to such XML export files. Not everything is possible to add to the project using Studio UI, but AFAIK much less restrictions applied if we use the Studio API classes.

Yes XML export is very inefficient, bloated, and although it could handle binary files as base64 encoded, but it would generate large files. For the initial implementation though we could ignore this inefficiency for the moment

Metadata file

2nd question to answer - what should we put as the metadata info? Certainly there should be “dependency information” (to make possible recursive install of all dependent packages), but what else?

Here is the example of metadata information from some abstract CPAN module using ExtUtils::AutoInstall package functions, which is not usually part of distribution, but one has handy facility for dependency tracking:

use inc::Module::Install; name 'Joe-Hacker'; abstract 'Perl Interface to Joe Hacker'; author 'Joe Hacker <joe@hacker.org>'; include 'Module::AutoInstall'; requires 'Module0'; # mandatory modules feature 'Feature1', -default => 0, 'Module2' => '0.1'; auto_install( make_args => '--hello', # option(s) for CPAN::Config force => 1, # pseudo-option to force install do_once => 1, # skip previously failed modules ); WriteAll;

Here is the example of NPM package dependencies description:

{ "dependencies" :
 { "foo" : "1.0.0 - 2.9999.9999"
 , "bar" : ">=1.0.2 <2.1.2"
 , "qux" : "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0"
 , "asd" : "http://asdf.com/asdf.tar.gz"
 , "til" : "~1.2"
 , "elf" : "~1.2.3"
 , "lat" : "latest"
 , "dyl" : "file:../dyl"
 }
}

As a rough approximation, we could start with JSON format used by the NPM packages. However, for the simplicity sake, before we have better JSON support in the kernel, we could start with XML metadata file information.

Honestly, I hate XML, but let face it - XML and JSON are quite interchangeable, and all about the same, they are 2 different way to serialize hierarchical info. So whatever is described in JSON, could be similarly described in XML, and vice versa.
Once we have better JSON support in the product, we could easily switch the gears, and use JSON instead of XML for metadata information file.

Dependency on system classes

When we are talking about dependencies on some classes there is interesting problem to address - how to mark dependency on some “built-in” Caché/Ensemble/HealthShare/TrakCare class(es), which may have been introduced with some particular version? And in general - how to denote dependency on anything from %CACHELIB and similar system database?

For simplicity matter (in the initial implementation) we may just ignore that problem, and if deployed extra class will reference to anything of system database then just assume it’s just there.

In the ideal case we should have facilities to require dependency on some particular version (i.e. “>2014.1”) of particular product (“Cache”, “Ensemble”, “HealthShare”, “EM”, etc.) or even some particular package installed (“iKnow”, “SetAnalysis”, etc) This is too early though at the moment to try to invent some definitive mechanism, so we may leave this question unanswered.

Cross-platform binary modules

CPAN would not get so much success if there would be no way to distribute packages, which are partially implemented in C, and part in Perl. So for calling to some mission critical, highly optimized code, or as a wrappers for sokme externally available C/C++ library. In Perl they have XS API facilities which allows you to call C code from Perl module, and in reverse. If you would look into the implementation details you would quickly realize that XS is modelled very similar to Caché callout - similarly as in our case, there is no simple and direct wayto call any C/C++ API, you have to write wrapper to call it. But dislike to callout there are available a number of service utilities which simplify the process of a wrapper creation, such as:

  • h2xs preprocessor to generate XS header using the given C header file (well with some limitations);
  • xsubpp - preprocessor to convert XS code to pure C code, etc;

While dealing with callout code from COS we have a little help from the system, and most of the code should be written manually. [Fortunately, now we are allowed to write DLL callouts, and not obliged to statically recompile Caché kernel, the situation I remember at the early 2000]

There are a couple of rather modern, and relatively convenient approaches to call external C/C++ code from Caché kernel:

From the practical prospective though, taking into account multiple Caché platforms we should handle equally well (Windows, Linux, Mac OS X, oreven VMS), and the fact that these both FFI (foreign-function interfaces) are not yet officially supported, I should admit that they both are not ready yet, and could not be recommended as a way to handle deployment of mixed C/COS packages. Now it’s not a big issue, but eventually, once we will go to cross-platform with binary packages we should revisit this topic.

Unit Testing

CPAN example showed us yet another good practice, which may positively affect the maturity and stability of 3rd party eco-system – built-in testing support. Each popular Perl package had built-in set of unit-test, which supposed to be run after compilation completed and before installation happen. If there this unit-testing is not passed for the target system then installation will not happen.

For simplicity sake we may ignore unit-testing support in the 1st implementation, but once it will evolve to the binary package format (i.e. ZIP) and binary modules support added – then testing should become required step before installation.

Command-line access

User experience is a key factor here - if this system would be inconvenient to use then there is big chance to stay unnoticed. To be useful for COS developers community here we supposed to handle “package installations” both directions:

  • be it invoked from COS shell, via simple package-manager shell `do ^CPM`
  • or from command-line, i.e. `cpm install DeepSee-Mobile`
From practical point of view they should be interchangeable and provide the same side-effect for each operation. But having CLI access to package manager is important for administrators due to scripting needs.
In the longer term, once infrastructure is established and mature enough there should be developed GUI wrapper for package manipulations (say, callable from SMP), but GUI is not required at the 1st step.

Mirroring and CDN

In 199x-200x years each package management system faced yet another problem, they had to address separately - how to make their repository respond fast, and preferably from geo-optimized mirror location? And while we are at this topic - what about that mirror system should be DDoS resistant at the same time? Such “old school” software repositories usually relied on community power to deploy huge network of geo-spread mirrors (CPAN, CTAN, Debian, etc.). They are still using the same approach, and still have multiple mirrors spread over the planet, but today we have easier soluion to this same problem.

Today there is available a cheap facility of CDN providers. If we need to just host some set of static binary files then CDN is just “that doctor ordered”. I have no idea who is the best selection for our scenario: whether it will be some generic VM-hosting provider like Amazon or Azure, or, may be, we would need to select between Amazon CloudFront, or MaxCDN or anything similar. Anything of mentioned is easy to handle nowadays, and not require any extra mirroring effort from the community.

If you have any prior experience with CDN, and have strong preference on something, please provide us advice - we will be curios to know any details.

Final words

This is my simple take on the apparent problem of missing convenient repository for 3rd party components used in Caché database problem. They are either hard to find, or hard to install, or unmaintained, or all at once. We need more utilities, more classes available, and more developers involved in the ecosystem. Central repository like CPAN could be a trigger point in changing the scenario of how an average Joe "the COS developer" develops their new solutions.

I hope it's clear now that package manager might be doable right now, even with current database platform support, and could be done in reasonable amount of time. So...

So who is wanting to participate? Do we have community demand here?

Intersystems Caché - Approaching Community Package Manager - Part I

​ Here is the problem as I see in the Caché developers community - if you are newbie COS/Ensemble/DeepSee developer then it's very hard to find any suitable 3rd party component, library or utility. They are spread over the Internet, some of them are in the GitHub, some of them in SourceForce, rare ones are on their own sites, etc. Yes,there are many useful components or tools (there are even standalone debugger or VCS) but it takes some time to discover all the useful location, and get to used to this situation.
There is no single location and there is no convenient way to find and install extension or utility.
Which is not very competitive comparing to other languages and development environment. In these articles I will try to investigate this problem further (this part I), and will propose some simple decision (part II)

​What do you think about "package manager" and its importance for the community success? For me, package manager is absolutely a must, and most important ingredient for the language success and maturity of eco-system. You could not find any single language community where there would be no convenient package manager with huge collection of available 3rd party packages. After all these years spent hacking in Perl, Python, JavaScript, Ruby, Haskell, Java, (you name other) you pretty much used to expect that when you start a new project you have a plenty of external components which may help you to cook the project fast and seamless. `PM install this`, `PM install that` and quite easy and fast you get something working and useable. Community works for you.

These words about CPAN and its experience are pretty much characterizing the importance of the precedent of CPAN and it's later impact toother languages and environments:

"Experienced Perl programmers often comment that half of Perl's power is in the CPAN. It has been called Perl's killer app.Though the TeX typesetting language has an equivalent, the CTAN (and in fact the CPAN's name is based on the CTAN), few languages have an exhaustive central repository for libraries. The PHP language has PECL and PEAR Python has a PyPI (Python Package Index) repository, Ruby has RubyGems R has CRAN Node.js has npm Lua has LuaRocks Haskell has Hackage and an associated installer/make clone cabal but none of these are as large as the CPAN. Recently, Common Lisp has a de facto CPAN-like system - the Quicklisp repositories. Other major languages, such as Java and C++, have nothing similar to the CPAN (though for Java there is central Maven).
The CPAN has grown so large and comprehensive over the years that Perl users are known to express surprise when they start to encounter topics for which a CPAN module doesn't exist already."

RPM

Other

OS X (pkg)

and

Application Extensions

Application extensions

Cross-platform

Source redacted - https://en.wikipedia.org/wiki/Package_manager

Here you see the redacted (significantly simplified) picture of WikiPedia article about package managers. They are a lot, be them source-based, or binary-based ones, particular architecture specific, OS-specific or cross-platform. I will try to cover them to some degree below. I will mix to the picture some language-specific package-management facilities, because without them picture would be of no much usefulness. And we are talking about language-/development-platform specific package managers in any case...

One important observation you could get from the table above – the more popular particular operating system and API ecosystem is, the more chances you have to receive multiple concurrent package managers for this platform. See situation in the Linux, Windows or Mac OS X as good examples. The more package managers used out there, the faster ecosystem is evolving. Having multiple package managers is not a requisite for fast ecosystems development pace, but rather side-effect of one.
Simply putting - if we eventually would get the situation where we would have several package managers with different repositories, than that would be rather indication about good ecosystem state, not bad.

Simplified timeline

Here is the approach I will use: get most important operating systems and language package managers, put them to the timeline, explain their specifics and interest for us, then do some generalizations and conclusions for Caché as a platform.

As we all know "picture worth a thousand word" so trying to simplify explanation I have drawn this silly timeline, which references all "important" (from my personal point of view) package managers which were used till the moment. Upper part is about language-specific package managers, and lower part is about operating system/distribution specific ones. X-axis steps is by 2 years (from January 1992 until today).

Package managers: Timeline from 1992 till 2014

CTAN, CPAN & CRAN

90ties were years of source-based package managers. We already had internet working as a distribution manager, but all package managers were operating on the same scenario:

  • Given the requested package name PM has downloaded the resolved tar-file;
  • Extracted it locally to the user/site specific area;
  • And invoked some predefined script for "building" and installing those sources to the locally installed distribution.

CTAN was the 1st language distribution which established such handy practice to install contributed content (Tex packages and extensions) from central repository. However, real explosion to this model happened when Perl community started to employ this model – since the moment of CPAN inception in the 1995 it collected "140,712 Perl modules in 30,670 distributions, written by 11,811 authors, mirrored on 251 servers."

This is very comfortable to work with language and within environment where for each next task you have the 1st question you ask: "Whether there is already module created for XXX?" and only in a couple of seconds (well minutes, taking into consideration the internet speed in middle-late nineties) after the single command executed, say:

>cpan install HTTP::Proxy

You have this module downloaded, source extracted, makefile generated, module recompiled using this generated makefile, all tests ran, sources, binaries and documentation installed into the local distribution and all is ready to use in your Perl environment via simple "use HTTP::Proxy;"!

Worth to mention that most of CPAN modules are Perl-only packages (i.e. beyond Perl Makefile.pl there are only source files written in Perl, thus not extra processing is necessary, which is simplifying deployment). But also worth to note that Perl Makefile.pl is flexible enough to easily handle combination of Perl sources with some binary modules (e.g. program, which is usually written in C, which in turn to be downloaded and compiled locally, using target specific compiler and its ABI).

The same model used by Tex in CTAN, and Perl in CPAN, developers of statistical language R tried to use in CRAN. The similar repository (archive) of all available sources, and similar infrastructure for easy download and install. The problem with CRAN was the language (R) which was not very famous and so widespread as Tex or Perl. But regardless this fact even "relatively rarely used R" accumulated 6000+ packages of extensions.

BSD world: FreeBSD Ports, NetBSD pkgsrc, and Darwin Ports

At the same period in the middle of 90-ies, FreeBSD introduced their own way to distribute open-source software via their own "ports collection". Various BSD-derivatives (like OpenBSD and NetBSD) maintained their own ports collections, with few changes in the build procedures, or interfaces supported. But in any case the basic mechanism was the same after `cd /port/location; make install` invoked:

  • Sources were installed from appropriate media (be it CD-ROM, DVD or internet site);
  • Product built using the Makefile given and compiler(s) available;
  • And build targets installed according to the rules written in the Makefile or other package definition file;

There was an option to handle all dependencies of a given port if there was request, so full installation for bigger package could still be initiated via single command and package manager handled all the recursive dependencies appropriately.

From the license and their predecessors prospective I consider Darwin Ports/MacPorts as the derivative of this BSD port collection idea – we still have the collection of open source software, which is conveniently handled by a single command, i.e.:

$ sudo port install apache2
It's worth to emphasize – until the moment both language-based repositories (CTAN/CPAN/CRAN) and BSD port collections (FreeBSD/OpenBSD/NetBSD/MacPorts) were all representing the 1st class of package-managers - sourcecode-based package managers

Linux: Debian and Red Hat

Sourcecode-based package management model was working well (till some degree) and produced impression of full transparency and full control. There were only several "small" problems:

  • Not all software could be deployed in source form, there is real life beyond open-source software, and proprietary software still need to be deployed conveniently;
  • And building of a big project may took a huge chunk of time(hours).

There was apparently a need to establish a way to distribute packages (and all dependencies) in their binary form, already compiled for the given architecture and ready for consumption. So we introduce binary package formats, and the 1st which of some interest for us – is the .deb format use by Debian package manager (dpkg). Original format, introduced in the Debian 0.93 in the March 1993, was just the tar.gz wrapper with some magic ASCII prefixes. Currently .deb package is both simpler and more complex – it's just the AR archive consisting of 3 files (debian-binary with version, control.tar.gz with metadata and data.tar.* with the installed files). You are rarely using dpkg in the practice - most current Debian-based distributives are using APT (advanced packaging tool). Surprisingly (at least for me for the moment I started to write this review) APT has outgrown Debian distros, and has been ported to Red Hat based distros (APT-RPM), or Mac OS X (Fink), or even Solaris.

"Apt can be considered a front-end to dpkg, friendlier than the older dselect front-end. While dpkg performs actions on individual packages, apt tools manage relations (especially dependencies) between them, as well as sourcing and management of higher-level versioning decisions (release tracking and version pinning)."

https://en.wikipedia.org/wiki/Advanced_Packaging_Tool

The apt-get' reach functionality and easiness has influenced all later package managers.

Another good example for binary packaging systems is the RPM (Red Hat Package Manager). RPM introduced with Red Hat V2.0 the late 1995. Red Hat quickly became the most popular Linux distribution (and solid RPM features was one of the factors winning competition here, till some moment at least). So it is not a big surprise that RPM started to be used by all RedHat-based distributions (e.g. Mandriva, ASPLinux, SUSE, Fedora or CentOS), but even further, beyond Linux it was also used by Novell Netware, or IBM AIX.

Similar to APT/dpkg there is Yum wrapper for RPM packages, which is frequently used by end-users, and which provides similar high-level services like dependency tracking or building/versioning.

Mobile software stores: iOS App Store, Android Market/Google Play

Since the introduction of Apple iOS App Store, and later Google Android Market, we have received most probably most popular software repositories which we have seen to date. They are essentially OS specific package managers with extra API for online purchases. This is not yet an issue for App Store, but is an issue for Android Market / Google Play – there are multiple hardware architectures used by Android devices (ARM, X86 and MIPS at the moment), so there are some extra care should be done before customer could download and install binary package containing executable code for some application. Given hardware agnostic Java code, you either supposed to compile Java-to-native binary upon installation on the target device, or repository itself could take care about this and recompile the code (with full optimizatons enabled) on the cloud, before downloading to the customer device.

In any case, regardless of where and how such optimizing native adaptation is done, this part of installation process is considered a major part of software packaging services done by operating system. If software supposed to be running on many hardware architectures, and if we are not deploying software in the source-code form (as we done in BSD or Linux) then repository and package maneeger should handle this problem transparently and in an some efficient manner.

For a time being, I'm not considering any cross-platform issues, and will handle in the 1st implementation only fully open-source packages. We may return back to this question later, to resolve both cross-version and cross-architecture issues simulateneously.

Windows applications: Chocolatey Nuget

It was a long-standing missing feature - despite the popularity of Windows on the market, we didn't have any central repository, as convenient as for Debian is apt-get, where we could find and install any (many/most) of available applications. There used to be Windows Store for Windows Metro applications (but nobody wanted to use them :) ), even before then, there used to be nice and convenient NuGet package manager, installed as plugin to Visual Studio, but (the impression was that) it was only serving .NET packages, and was not targeting "generic Windows desktop applications". Even farther, there was Cygwin repository, where you could download (quite conveniently though) all Cygwin applications (from bash, to gcc, to git, or X-Window). But this was, once again, not about "any generic windows application", but only about ported POSIX (Linux, BSD, and other UNIX compatible APIs) applications which could be recompiled using Cygwin API.

That's why development of Chocolatey Nuget in 2012 got me as a nice surprise: apparently having NuGet as a basis for package manager, with added PowerShell woodoo upon installation, and with added some central repository here you could pretty much have the same convenience level as with apt-get in Linux. Everything could be deployed/wrapped as some Chocolatey package, from Office 365, to Atom editor, or Tortoise Git , or even Visual Studio 2013 Ultimate! This quickly became the best friend of Windows IT administrator, and many extra tools used Chocolatey as their low-level basis have been developed, best example of such is - BoxStarter, the easiest and fastest way to install Windows software to the fresh Windows installations.

Chocolatey shows nothing new, which we didn't see before in other operating systems, it just shows that having proper basis (NuGet as a package manager, PowerShell for post-processing, + capable central repository) one could built generic package manager which will attract attention quite fast, even for the operating system where it was unusual. BTW, worth to mention that Microsoft decided to jump to the ship, and are now using Chocoatey as one of repositories, which will be available in their own OneGet package manager to be available since Windows 10.

On a personal note, I should admit, I do not like OneGet as much as I like Chocolatey - there is too much PowerShell scripting I'd need to plumbing for OneGet. And from user experience prospective Chocolatey hides all these details, and is looking much, much easier to use.

Node.js NPM

There are multiple factors which have led to recent dramatical success of JavaScript as a server-side language. And one of most important factors in this success (at least IMVHO) - the availability of central Node.js modules repository - NPM (Node Package Manager) . NPM is bundled with Node.js distribution since version 0.6.3 (November 2011).

NPM is modeled similarly as CPAN: you have a wrapper, which from command-line connects to central repository, search for requested module, download it, parse package metainfo, and if there are external dependencies then process this recursively. In a few moments, you have working binaries and sources available for local usage:

C:\Users\Timur\Downloads>npm install -g less
npm http GET https://registry.npmjs.org/less
npm http 304 https://registry.npmjs.org/less
npm http GET https://registry.npmjs.org/graceful-fs
npm http GET https://registry.npmjs.org/mime
npm http GET https://registry.npmjs.org/request
…
npm http GET https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz
npm http 200 https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz
npm http 200 https://registry.npmjs.org/asn1
npm http GET https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz
npm http 200 https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz
C:\Users\Timur\AppData\Roaming\npm\lessc -> C:\Users\Timur\AppData\Roaming\npm\node_modules\less\bin\lessc
less@2.0.0 C:\Users\Timur\AppData\Roaming\npm\node_modules\less
├── mime@1.2.11
├── graceful-fs@3.0.4
├── promise@6.0.1 (asap@1.0.0)
├── source-map@0.1.40 (amdefine@0.1.0)
├── mkdirp@0.5.0 (minimist@0.0.8)
└── request@2.47.0 (caseless@0.6.0, forever-agent@0.5.2, aws-sign2@0.5.0, json-stringify-safe@5.0.0, tunnel-agent@0.4.0, stringstream@0.0.4, oauth-sign@0.4.0, node-uuid@1.4.1, mime-types@1.0.2, qs@2.3.2, form-data @0.1.4, tough-cookie@0.12.1, hawk@1.1.1, combined-stream@0.0.7, bl@0.9.3, http-signature@0.10.0)

Wortth to note that changes which NPM authors introduce to the package manager practices - they use JSON format for package metainformation, instead of Perl-based ones used in the CPAN.

To be continued…

Ok, enough about current practice used elsewhere, in the 2nd part of this article we will talk more in details about simple proposal for a package manager in Caché. Stay tuned!.​

четверг, 16 октября 2014 г.

Intersystems Meetup в Питере