Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiling cells-sync under ARM64 (running DSM - a Linux distro for the Synology NAS): the nightmare #37

Open
GwynethLlewelyn opened this issue Aug 16, 2021 · 1 comment

Comments

@GwynethLlewelyn
Copy link

In my never-ending quest of getting the Pydio Cells family of services running on as many platforms as I can, I've been tackling a years-old issue I have: how to synchronize between a Synology NAS and a remote Pydio Cells installation.

The 'obvious' choice would be just to get the Synology NAS to sync over its one-size-fits-all S3 sync solution, which works with pretty much everything... except Pydio Cells. Alas, that's a completely different issue and not relevant today.

Instead, after a complex procedure that allowed me to compile CGo packages for the ARM64 architecture on the Synology NAS — something which eluded me for months, too — I managed to get a lot more things to compile there, so I thought I could give CellsSync a try. Although Synology's DSM (= DIskStation Manager) is essentially a GNU/Linux distro, its configuration is somewhere between macOS and Debian Linux (coming closer to Debian Linux these days, since it already uses a systemd setup, although it doesn't ship with a package manager — deliberately so, you're not supposed to tinker with the operating system...). By far the easiest non-supported programming language to get working on the Synology DSM is Go (at least when compared to C/C++...), so, once you get Go compiling basically everything, it's supposed to compile Cells Sync as well.

While I don't need the GUI version of Cells Sync, it seems that somehow the Makefile 'assumes' that the installation is 'complete', that is, that the whole UX is ready to be installed — even if it won't. Unfortunately, the Synology NAS is not meant to be an application development environment — it's way too slow for that. Fortunately, Go is blazing fast everywhere — and thus also on a slow ARM64 with a small memory footprint! — but, alas, that's not the case for practically anything else. npm takes eternities to do anything worthy.

npm WARN deprecated @babel/[email protected]: 🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.
npm WARN deprecated [email protected]: core-js@<3.3 is no longer maintained and not recommended for usagedue to the number of issues. Because of the V8 engine whims, feature detection in old core-js versionscould cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.
npm WARN deprecated [email protected]: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.
npm WARN deprecated [email protected]: This loader has been deprecated. Please use eslint-webpack-plugin
npm WARN deprecated [email protected]: please switch to a stable version
npm WARN deprecated [email protected]: "Please update to latest v2.3 or v2.2"
npm WARN deprecated [email protected]: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15xless dependencies.
npm WARN deprecated [email protected]: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142
npm WARN deprecated [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated [email protected]: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.
npm WARN deprecated [email protected]: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated [email protected]: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm WARN deprecated @hapi/[email protected]: Switch to 'npm install joi'
npm WARN deprecated [email protected]: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added
npm WARN deprecated [email protected]: this library is no longer supported
npm WARN deprecated @hapi/[email protected]: Moved to 'npm install @sideway/address'
npm WARN deprecated @hapi/[email protected]: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/[email protected]: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/[email protected]: This version has been deprecated and is no longer supported ormaintained
npm WARN deprecated [email protected]: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated [email protected]: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated [email protected]: use String.prototype.padStart()

> [email protected] postinstall /volume1/homes/gwyneth/go/src/github.com/pydio/cells-sync/app/ux/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"

Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!

The project needs your help! Please consider supporting of core-js on Open Collective or Patreon:
> https://opencollective.com/core-js
> https://www.patreon.com/zloirock

Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)


> [email protected] postinstall /volume1/homes/gwyneth/go/src/github.com/pydio/cells-sync/app/ux/node_modules/oidc-client/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"

Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!

The project needs your help! Please consider supporting of core-js:
> https://opencollective.com/core-js
> https://patreon.com/zloirock
> https://paypal.me/zloirock
> bitcoin: bc1qlea7544qtsmj2rayg0lthvza9fau63ux0fstcz

Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)


> [email protected] postinstall /volume1/homes/gwyneth/go/src/github.com/pydio/cells-sync/app/ux/node_modules/react-app-polyfill/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/react-scripts/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"arm64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules/jest-haste-map/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"arm64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"arm64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.3.2 (node_modules/watchpack/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"arm64"})
npm WARN [email protected] requires a peer of @types/react@>=16.3.0 <17.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of @types/react-dom@>=16.3.0 <17.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @uifabric/[email protected] requires a peer of @types/react@>=16.3.0 <17.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @uifabric/[email protected] requires a peer of @types/react-dom@>=16.3.0 <17.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @uifabric/[email protected] requires a peer of @types/react@^0.14.x || ^15.x || ^16.x but noneis installed. You must install peer dependencies yourself.
npm WARN @uifabric/[email protected] requires a peer of @types/react-dom@^0.14.x || ^15.x || ^16.x but none is installed. You must install peer dependencies yourself.
npm WARN @typescript-eslint/[email protected] requires a peer of typescript@* but none is installed. You must install peer dependencies yourself.
npm WARN @typescript-eslint/[email protected] requires a peer of typescript@* but none is installed.You must install peer dependencies yourself.
npm WARN @babel/[email protected] requires a peer of @babel/core@^7.12.0 but none is installed. You must install peer dependencies yourself.
npm WARN @babel/[email protected] requires a peer of @babel/core@^7.13.0 but none is installed. You must install peer dependencies yourself.
npm WARN @typescript-eslint/[email protected] requires a peer of typescript@* but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of acorn@^6.0.0 but none is installed. You must install peer dependencies yourself.

added 1615 packages from 840 contributors and audited 1623 packages in 367.931s

75 packages are looking for funding
  run `npm fund` for details

found 11 vulnerabilities (1 low, 7 moderate, 3 high)
  run `npm audit fix` to fix them, or `npm audit` for details

Predictably:

$ npm run build

> [email protected] build /volume1/homes/gwyneth/go/src/github.com/pydio/cells-sync/app/ux
> react-scripts build

Creating an optimized production build...


<--- Last few GCs --->

[32026:0x3a01c720]  1726166 ms: Scavenge 426.3 (432.1) -> 426.2 (434.6) MB, 48.6 / 0.0 ms  (average mu= 0.207, current mu = 0.291) allocation failure
[32026:0x3a01c720]  1727101 ms: Mark-sweep 428.3 (434.6) -> 426.9 (434.1) MB, 831.0 / 0.4 ms  (+ 250.2ms in 82 steps since start of marking, biggest step 35.3 ms, walltime since start of marking 1276 ms) (average mu = 0.209, current mu = 0.240) allocatio

<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x13f274c]
    1: StubFrame [pc: 0x1374188]
Security context: 0x00005f49b989 <JSObject>
    2: /* anonymous */ [0x7f73d93a79] [/volume1/homes/gwyneth/go/src/github.com/pydio/cells-sync/app/ux/node_modules/webpack-sources/node_modules/source-map/lib/source-node.js:~86] [pc=0x3fe8cb88](this=0x007fa9461cf1 <JSFunction SourceNode (sfi = 0x48ff0a59)>,0x0000508bde09 <Object map = 0x7f71684da9>)
    3: arguments adaptor fra...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `react-scripts build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
[...]

(if you wish, I can send that log as well)

FYI, I've tried to 'modularise' Cells Sync and Pydio Cells, after noticing that Cells Sync relies on a common directory which is used by Cells Sync... ugh. You really should put those common files on a separate repository, simply because building a CLI version for Cells Sync ought to be substantially easier to compile than the whole Pydio Cells mega-package! Or so I'd expect, anyway. After 4 days of making a serious attempt to get everything modularised, I had to give up (and trust me, I don't usually give up easily!).

I believe that the main issue with the current Pydio Cells suite is its dependencies of incredibly obsolete packages, most of which have quasi-circular dependencies. There are a few ones that are simple — packages that just changed their current location, something which applies to BoltDB and Caddy, for instance — and a few that are very hard, and are at the deep core of Pydio Cells (but not Cells Sync!... alas, you can't compile it without compiling Cells Sync as well). I understand that the main reason for this obsolescence was the need to start a large Go project before modules came around. As practically everybody switched to modules (Google does a yearly survey to its community, and it seems that around 96% of the Go developer community regularly uses modules), it becomes increasingly harder and harder to keep running a complex application-building environment that relies on other sources. To be more specific, the mere idea of using npm to handle Go module dependencies is, to be blunt, insane. Even the core Pydio Cells uses Go-specific, pre-module packages to handle those dependencies (at least, as far as I know).

Particularly hard to fix are the dependencies around the go-micro package (extensively used by Cells to provide an environment of microservices), mostly because there are at least three different packages doing the same (and using the same name). Two of those are simply major versions of the same package — but, under the rules of Go modules, each major version (because it's API-incompatible with the previous one), gets its own package & namespace (be it a Git branch or a completely separate repository). go mod can handle these easily, but the pre-modules system has a really tough time to deal with them — simply because some packages may also be updated and require the old major version, while newer packages, which have been updated, rely on the new major version. Go modules deals with those issues easily enough; the 'vendor' approach used by Pydio Cells gets hopelessly confused. Finally, there is a third source of go-micro. As far as I can see, some of the concepts are similar; they might even have started as a fork of each other, and then moved on in different directions. Pydio Cells sometimes needs subpackages of one, sometimes of the other. This is sadly unfortunate for those, like me, who are unaware of the real differences between them, and, just by looking at what the Pydio Cells source is including/requiring, it's not obvious which is which. Eventually, as the dependency tree grows, it becomes obvious when the 'wrong' package had been included, and that means going back and changing the import path just for that file, and move on with the generation of the dependency tree (i.e. go mod tidy).

The second big issue has to do with the usage of Google's protobuf implementation in Go — which, again, has seen several different releases, often incompatible with each other. Google has kindly left a reasonably old implementation available on GitHub (it's 5-6 years old, at the time of writing), but they seriously warn everybody to move on to the current, official version, which is not hosted on GitHub but on Google's own Git repository for Go-related things. So far, so good — you can continue to use the old version, after all — but the problem, not surprisingly, is similar to the one above: some packages used by Pydio Cells have never been updated, and use the old version of protobuf to generate their own protobuf bindings; others have been updated, and use the new version; and Pydio Cells itself knows nothing about 'different' protobuf packages, and gets in trouble if the 'wrong' one is included — mostly because, from the perspective of the Pydio Cells code, nothing is wrong: they just include a third-party package (which might even be up-to-date), which, in turn, is calling either the old or the new version of protobuf... and theoretically, from the PoV of the Cells developers, that's a problem to be fixed upstream; they just know what to call from the third-party package, and are assuming that whatever it depends upon is handled correctly. And, actually, it is... with Go modules, which tell exactly what has to be included, and the correct order for including all of that (even if different versions of the same package are used, Go modules will handle those cases easily as well). The problem is when one uses such third-party packages without using Go modules — then it means manually handling all dependencies correcly, and that will be true not only for the particular file/module/package one is working with, but for all of the others as well, since — well, since they can be importing different versions, too!

Right. You can see how this can quickly become exponential. But, as you might imagine, to make matters worse, go-micro relies heavily upon protobuf. And now Cells is including 3 versions of go-micro and at least two versions of protobuf, which means that, every time some import path requires to be fixed on a file that uses microservices, there are at least 6 different combinations to pick from, and only one of them will be correct. With a bit of luck, you might get it right for the handful of files inside one of the many Cells submodules (worst-case scenario: try 6 different combinations in turn, you'll get it right at least on the last try...).

Obviously, when I started doing all the above, I really had no idea how many different versions — and combinations of versions — were available. That meant that after 'fixing' a lot of dependencies on the several submodules, I finally hit one submodule where there was a new combination of versions that I hadn't encountered before. This meant dealing with it for that particular submodule (or file inside a submodule)... and hoping against hope that I had fixed the first submodules correctly. Murphy's Law, again, showed that not to be the case, so very quickly I was running in loops — getting dependencies right, one by one; getting stuck on a difficult case; fixing it, restarting from scratch; now the ones I had fixed before were, obviously, inconsistent, so I had to change them again. Run go mod tidy again... getting stuck on a new submodule, with a new (previously unknown) dependency. Fix it. Again... the early modules broke... so I had to start from scratch... and so forth.

Needless to say, after four days, I never managed to even get a fully working dependency tree. Every day (sometimes more than once) I had to restart with a 'clean' installation because things had become so hopelessly tangled that I lost the thread — the best choice was to start from scratch and rely on the knowledge I had acquired the day before. Wash, rinse, repeat.

Until, well, it simply was too much for me.

I now start to appreciate why @cdujeu never bothered with changing everything to Go modules :-)

On the other hand, at least cells-sync could have a CLI that did not depend on the whole of the UX and a fully-compiled installation of Pydio Cells. That would go a long, long way to make my job easier.

So I guess that I need to dig into the cells-sync code to figure out the 'magic' of syncing (uploads and downloads are trivial, especially when using cells-client, of course :-) ).

I know this has been a very long essay, but I hope you feel my frustration. Remember what my original intention was: having a way to sync folders from my home NAS to a remote server running Pydio Cells. That seems trivial enough, right? Well, one thing is to copy files in either direction. That's the easy bit. The other issue is to make Pydio Cells understand that new files have arrived, and index them. That's the tricky bit. Of course, I can always run the scheduler (manually) every now and then, to reindex the whole folder. Unfortunately, that takes 2-3 minutes (under my current scenario), and consumes a huge amount of resources (memory, CPU...) during those 2-3 minutes. What I need is to do the same thing that Cells Sync does: figure out what are the differences between the local and remote folders, send them over, and index them on-demand as they arrive. That means near-real-time sync'ing (just as is provided by Dropbox, OneDrive, Google Drive... and Cells Sync), as opposed to having to ask people to 'wait a bit until I manually resync the folders'. Note that, from the perspective of the operating system, the folders are in sync all the time (yay [rclone](https://github.com/rclone/rclone)!). The problem is that there is no easy and obvious way to inform Pydio Cells about the changes...

Aye, I'm also aware that I could theoretically connect to Pydio Cells using the Amazon S3 protocol. That, unfortunately, only seems to work for some cases but not others; I have absolutely no idea why (there are few logs to help me with a simple 'authentication denied' error). The exact credentials have no issue whatsoever with things such as Postman or even s3cmd; I guess that there is some step I might be missing...

@cdujeu
Copy link
Member

cdujeu commented Sep 16, 2021

nice read :-)
You get the point with modules. But we don't despair of switching to modules, that should be the next step after releasing v3. Our plan is actually to (maybe temporarily) split the code into pieces where the big dependencies should be built in their own different program : minio, caddy, etc... This should simplify that path. Although yes, go-micro is a big issue on that topic and at the heart of the whole stuff. But we'll do it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants