@rubeneschauzier/solidbench 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +211 -0
  3. package/bin/solidbench +2 -0
  4. package/bin/solidbench.d.ts +2 -0
  5. package/bin/solidbench.js +6 -0
  6. package/bin/solidbench.js.map +1 -0
  7. package/lib/CliRunner.d.ts +1 -0
  8. package/lib/CliRunner.js +20 -0
  9. package/lib/CliRunner.js.map +1 -0
  10. package/lib/Generator.d.ts +76 -0
  11. package/lib/Generator.js +231 -0
  12. package/lib/Generator.js.map +1 -0
  13. package/lib/Server.d.ts +19 -0
  14. package/lib/Server.js +34 -0
  15. package/lib/Server.js.map +1 -0
  16. package/lib/Templates.d.ts +14 -0
  17. package/lib/Templates.js +19 -0
  18. package/lib/Templates.js.map +1 -0
  19. package/lib/commands/CommandGenerate.d.ts +5 -0
  20. package/lib/commands/CommandGenerate.js +77 -0
  21. package/lib/commands/CommandGenerate.js.map +1 -0
  22. package/lib/commands/CommandServe.d.ts +5 -0
  23. package/lib/commands/CommandServe.js +50 -0
  24. package/lib/commands/CommandServe.js.map +1 -0
  25. package/lib/index.d.ts +4 -0
  26. package/lib/index.js +21 -0
  27. package/lib/index.js.map +1 -0
  28. package/package.json +68 -0
  29. package/templates/enhancer-config-pod.json +29 -0
  30. package/templates/enhancer-similarities-config-pod.json +39 -0
  31. package/templates/fragmenter-config-pod.json +525 -0
  32. package/templates/fragmenter-config-subject.json +63 -0
  33. package/templates/params.ini +5 -0
  34. package/templates/queries/README.md +43 -0
  35. package/templates/queries/interactive-complex-1.sparql +138 -0
  36. package/templates/queries/interactive-complex-10.sparql +89 -0
  37. package/templates/queries/interactive-complex-11.sparql +43 -0
  38. package/templates/queries/interactive-complex-12.sparql +36 -0
  39. package/templates/queries/interactive-complex-2.sparql +48 -0
  40. package/templates/queries/interactive-complex-3-duration-as-function.sparql +85 -0
  41. package/templates/queries/interactive-complex-3.sparql +85 -0
  42. package/templates/queries/interactive-complex-4-duration-as-function.sparql +36 -0
  43. package/templates/queries/interactive-complex-4.sparql +36 -0
  44. package/templates/queries/interactive-complex-5.sparql +55 -0
  45. package/templates/queries/interactive-complex-6.sparql +41 -0
  46. package/templates/queries/interactive-complex-7.sparql +84 -0
  47. package/templates/queries/interactive-complex-8.sparql +36 -0
  48. package/templates/queries/interactive-complex-9.sparql +45 -0
  49. package/templates/queries/interactive-discover-1.sparql +23 -0
  50. package/templates/queries/interactive-discover-2.sparql +23 -0
  51. package/templates/queries/interactive-discover-3.sparql +22 -0
  52. package/templates/queries/interactive-discover-4.sparql +23 -0
  53. package/templates/queries/interactive-discover-5.sparql +19 -0
  54. package/templates/queries/interactive-discover-6.sparql +22 -0
  55. package/templates/queries/interactive-discover-7.sparql +23 -0
  56. package/templates/queries/interactive-discover-8.sparql +22 -0
  57. package/templates/queries/interactive-short-1-nocity.sparql +33 -0
  58. package/templates/queries/interactive-short-1.sparql +34 -0
  59. package/templates/queries/interactive-short-2.sparql +39 -0
  60. package/templates/queries/interactive-short-3-unidir.sparql +27 -0
  61. package/templates/queries/interactive-short-3.sparql +32 -0
  62. package/templates/queries/interactive-short-4-creator.sparql +21 -0
  63. package/templates/queries/interactive-short-4.sparql +20 -0
  64. package/templates/queries/interactive-short-5.sparql +23 -0
  65. package/templates/queries/interactive-short-6.sparql +32 -0
  66. package/templates/queries/interactive-short-7.sparql +39 -0
  67. package/templates/query-config-single-pod.json +46 -0
  68. package/templates/query-config.json +778 -0
  69. package/templates/query-sequence-config.json +183 -0
  70. package/templates/refinements/interactive-discover-1.json +144 -0
  71. package/templates/refinements/interactive-discover-2.json +200 -0
  72. package/templates/refinements/interactive-discover-3.json +254 -0
  73. package/templates/refinements/interactive-discover-4.json +156 -0
  74. package/templates/refinements/interactive-discover-5.json +10 -0
  75. package/templates/refinements/interactive-discover-6.json +10 -0
  76. package/templates/refinements/interactive-discover-7.json +10 -0
  77. package/templates/refinements/interactive-discover-8.json +10 -0
  78. package/templates/refinements/interactive-short-1-bak.json +180 -0
  79. package/templates/refinements/interactive-short-1.json +65 -0
  80. package/templates/refinements/interactive-short-2.json +3 -0
  81. package/templates/server-config.json +72 -0
  82. package/templates/validation-config.json +644 -0
package/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright © 2021 - now Ruben Taelman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # SolidBench.js
2
+
3
+ [![Build status](https://github.com/SolidBench/SolidBench.js/workflows/CI/badge.svg)](https://github.com/SolidBench/SolidBench.js/actions?query=workflow%3ACI)
4
+ [![Coverage Status](https://coveralls.io/repos/github/SolidBench/SolidBench.js/badge.svg?branch=master)](https://coveralls.io/github/SolidBench/SolidBench.js?branch=master)
5
+ [![npm version](https://badge.fury.io/js/solidbench.svg)](https://www.npmjs.com/package/solidbench)
6
+
7
+ ### A benchmark for [Solid](https://solidproject.org/) to simulate vaults with social network data.
8
+
9
+ This benchmark allows you to generate a large amount of Solid data vaults with **simulated social network data**,
10
+ and serve them over HTTP using a built-in [Solid Community Server](https://github.com/CommunitySolidServer/CommunitySolidServer) instance.
11
+ Furthermore, different SPARQL queries will be generated to simulate workloads of social network apps for Solid.
12
+
13
+ This benchmark is based on the [LDBC SNB](https://github.com/ldbc/ldbc_snb_datagen_hadoop) **social network** dataset.
14
+
15
+ ## Requirements
16
+
17
+ * [Node.js](https://nodejs.org/en/) _(16 or higher)_
18
+ * [Docker](https://www.docker.com/) _(required for invoking [LDBC SNB generator](https://github.com/ldbc/ldbc_snb_datagen_hadoop))_
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ $ npm install -g solidbench
24
+ ```
25
+ or
26
+ ```bash
27
+ $ yarn global add solidbench --ignore-engines
28
+ ```
29
+
30
+ ## Quick start
31
+
32
+ 1. `$ solidbench generate`: Generate Solid data vaults with social network data.
33
+ 2. `$ solidbench serve`: Serve datasets over HTTP.
34
+ 3. Initiate HTTP requests over `http://localhost:3000/`, such as `$ curl http://localhost:3000/pods/00000000000000000933/profile/card`
35
+
36
+ ## Usage
37
+
38
+ ### 1. Generate
39
+
40
+ The social network data can be generated using the default options:
41
+
42
+ ```bash
43
+ $ solidbench generate
44
+ ```
45
+
46
+ **Full usage options:**
47
+
48
+ ```bash
49
+ solidbench generate
50
+
51
+ Generate social network data
52
+
53
+ Options:
54
+ --version Show version number [boolean]
55
+ --cwd The current working directory
56
+ [string] [default: .]
57
+ --verbose If more output should be printed [boolean]
58
+ --help Show help [boolean]
59
+ -o, --overwrite If existing files should be overwritten
60
+ [string] [default: false]
61
+ -s, --scale The SNB scale factor [number] [default: 0.1]
62
+ -e, --enhancementConfig Path to enhancement config
63
+ [string] [default: enhancer-config-pod.json]
64
+ -f, --fragmentConfig Path to fragmentation config
65
+ [string] [default: fragmenter-config-pod.json]
66
+ -q, --queryConfig Path to query instantiation config
67
+ [string] [default: query-config.json]
68
+ --validationParams URL of the validation parameters zip file
69
+ [string] [default: https://.../validation_params.zip]
70
+ -v, --validationConfig Path to validation generator config
71
+ [string] [default: validation-config.json]
72
+ --hadoopMemory Memory limit for Hadoop
73
+ [string] [default: "4G"]
74
+ ```
75
+
76
+ **Memory usage**
77
+
78
+ For certain scale factors, you may have to increase your default Node memory limit.
79
+ You can do this as follows (set RAM limit to 8GB):
80
+
81
+ ```bash
82
+ NODE_OPTIONS=--max-old-space-size=8192 solidbench.js generate
83
+ ```
84
+
85
+ **What does this do?**
86
+
87
+ This generate command will first use the (interactive) [LDBC SNB generator](https://github.com/ldbc/ldbc_snb_datagen_hadoop)
88
+ to **create one large Turtle file** with a given scale factor (defaults to `0.1`, allowed values: `[0.1, 0.3, 1, 3, 10, 30, 100, 300, 1000]).
89
+ The default scale factor of `0.1` produces around 5M triples, and requires around 15 minutes for full generation on an average machine.
90
+
91
+ Then, **auxiliary data** will be generated using [`ldbc-snb-enhancer.js`](https://github.com/SolidBench/ldbc-snb-enhancer.js/)
92
+ based on the given enhancement config (defaults to an empty config).
93
+
94
+ Next, this Turtle file will be **fragmented** using [`rdf-dataset-fragmenter.js`](https://github.com/SolidBench/rdf-dataset-fragmenter.js)
95
+ and the given fragmentation strategy config (defaults to a Solid vault-based fragmentation).
96
+
97
+ Then, **query** templates will be instantiated based on the generated data.
98
+ This is done using [`sparql-query-parameter-instantiator.js`](https://github.com/SolidBench/sparql-query-parameter-instantiator.js)
99
+ with the given query instantiation config (defaults to a config instantiating [all LDBC SNB interactive queries](https://github.com/SolidBench/SolidBench.js/tree/master/templates/queries)).
100
+
101
+ Finally, **validation queries and results** will be generated.
102
+ This is done using [`ldbc-snb-validation-generator.js`](https://github.com/SolidBench/ldbc-snb-validation-generator.js/) with the given validation config.
103
+ This defaults to a config instantiating all queries and results from the `validation_params-sf1-without-updates.csv` file from LDBC SNB.
104
+ This default config will produce queries and expected results in the `out-validate/` directory,
105
+ which are expected to be executed on a scale factor of `1`.
106
+
107
+ ### 2. Serve
108
+
109
+ The social network data can be served over HTTP as actual Solid vaults:
110
+
111
+ ```bash
112
+ $ solidbench serve
113
+ ```
114
+
115
+ **Full usage options:**
116
+
117
+ ```bash
118
+ solidbench serve
119
+
120
+ Serves the fragmented dataset via an HTTP server
121
+
122
+ Options:
123
+ --version Show version number [boolean]
124
+ --cwd The current working directory [string] [default: .]
125
+ --verbose If more output should be printed [boolean]
126
+ --help Show help [boolean]
127
+ -p, --port The HTTP port to run on [number] [default: 3000]
128
+ -b, --baseUrl The base URL of the server [string]
129
+ -r, --rootFilePath Path to the root of the files to serve
130
+ [string] [default: "out-fragments/http/localhost_3000/"]
131
+ -c, --config Path to server config
132
+ [string] [default: server-config.json]
133
+ -l, --logLevel Logging level (error, warn, info, verbose, debug, silly)
134
+ [string] [default: "info"]
135
+ ```
136
+
137
+ **What does this do?**
138
+
139
+ The fragmented dataset from the preparation phase is loaded into the [Solid Community Server](https://github.com/CommunitySolidServer/CommunitySolidServer)
140
+ so that it can be served over HTTP.
141
+
142
+ The provided server config uses a simple file-based mapping, so that for example the file in `out-fragments/http/localhost:3000/pods/00000000000000000933/profile/card` is served on `http://localhost:3000/pods/00000000000000000933/profile/card`.
143
+ Once the server is live, you can perform requests such as:
144
+
145
+ ```bash
146
+ $ curl http://localhost:3000/pods/00000000000000000933/profile/card
147
+ ```
148
+
149
+ ## Data model
150
+
151
+ By default, the following data model is used where all triples are placed in the document identified by their subject URL.
152
+
153
+ ![](https://raw.githubusercontent.com/ldbc/ldbc_snb_docs/dev/figures/schema-comfortable.png)
154
+
155
+ Query templates can be found in [`templates/queries/`](https://github.com/rubensworks/solidbench.js/tree/master/templates/queries).
156
+
157
+ ## Pod-based fragmentation
158
+
159
+ By default, data will be fragmented into files resembling [Solid data pods](https://solidproject.org/).
160
+
161
+ For example, a generated pod can contain the following files:
162
+
163
+ ```text
164
+ pods/00000000000000000290/
165
+ comments/
166
+ 2010-12-02
167
+ 2012-07-14
168
+ noise/
169
+ NOISE-1411
170
+ NOISE-83603
171
+ posts/
172
+ 2010-02-14
173
+ 2012-09-09
174
+ profile/
175
+ card.
176
+ settings/
177
+ publicTypeIndex
178
+ ```
179
+
180
+ All files are serialized using the [N-Quads serialization](https://www.w3.org/TR/n-quads/).
181
+
182
+ The `noise/` directory contains dummy triples with the main purpose of increasing the size of a pod.
183
+ The amount of noise that is produced can be configured using the enhancement config file.
184
+
185
+ Below, a minimalized example of the contents of a profile can be found:
186
+ ```turtle
187
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://www.w3.org/ns/solid/terms#publicTypeIndex> <http://localhost:3000/pods/00000000000000000290/settings/publicTypeIndex> .
188
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/Person> .
189
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://www.w3.org/ns/pim/space#storage> <http://localhost:3000/pods/00000000000000000290/> .
190
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/id> "290"^^<http://www.w3.org/2001/XMLSchema#long> .
191
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/firstName> "Ayesha" .
192
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/lastName> "Baloch" .
193
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/gender> "male" .
194
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/hasInterest> <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/tag/John_the_Baptist> .
195
+ <http://localhost:3000/pods/00000000000000000290/profile/card#me> <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/knows> _:b4_knows00000000000000124063 .
196
+ _:b4_knows00000000000000124063 <http://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/hasPerson> <http://localhost:3000/pods/00000000000000001753/profile/card#me> .
197
+ ```
198
+
199
+ ## Limitations
200
+
201
+ At this stage, this benchmark has the following limitations:
202
+
203
+ - Vaults don't make use of authentication, and all data is readable by everyone without authentication.
204
+ - SPARQL update queries for modifying data within vaults are not being generated yet: https://github.com/SolidBench/SolidBench.js/issues/3
205
+ - All vaults make use of the same vocabulary: https://github.com/SolidBench/SolidBench.js/issues/4
206
+
207
+ ## License
208
+
209
+ This software is written by [Ruben Taelman](https://rubensworks.net/).
210
+
211
+ This code is released under the [MIT license](http://opensource.org/licenses/MIT).
package/bin/solidbench ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./solidbench.js')
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const CliRunner_1 = require("../lib/CliRunner");
5
+ (0, CliRunner_1.runCli)(process.cwd(), process.argv);
6
+ //# sourceMappingURL=solidbench.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solidbench.js","sourceRoot":"","sources":["solidbench.ts"],"names":[],"mappings":";;;AACA,gDAA0C;AAE1C,IAAA,kBAAM,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { runCli } from '../lib/CliRunner';\n\nrunCli(process.cwd(), process.argv);\n"]}
@@ -0,0 +1 @@
1
+ export declare function runCli(cwd: string, argv: string[]): void;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runCli = runCli;
7
+ const yargs_1 = __importDefault(require("yargs"));
8
+ const helpers_1 = require("yargs/helpers");
9
+ function runCli(cwd, argv) {
10
+ const _ = (0, yargs_1.default)((0, helpers_1.hideBin)(argv))
11
+ .options({
12
+ cwd: { type: 'string', default: cwd, describe: 'The current working directory', defaultDescription: '.' },
13
+ verbose: { type: 'boolean', describe: 'If more output should be printed' },
14
+ })
15
+ .commandDir('commands')
16
+ .demandCommand()
17
+ .help()
18
+ .parse();
19
+ }
20
+ //# sourceMappingURL=CliRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CliRunner.js","sourceRoot":"","sources":["CliRunner.ts"],"names":[],"mappings":";;;;;AAGA,wBAUC;AAbD,kDAA0B;AAC1B,2CAAwC;AAExC,SAAgB,MAAM,CAAC,GAAW,EAAE,IAAc;IAChD,MAAM,CAAC,GAAG,IAAA,eAAK,EAAC,IAAA,iBAAO,EAAC,IAAI,CAAC,CAAC;SAC3B,OAAO,CAAC;QACP,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,+BAA+B,EAAE,kBAAkB,EAAE,GAAG,EAAE;QACzG,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,kCAAkC,EAAE;KAC3E,CAAC;SACD,UAAU,CAAC,UAAU,CAAC;SACtB,aAAa,EAAE;SACf,IAAI,EAAE;SACN,KAAK,EAAE,CAAC;AACb,CAAC","sourcesContent":["import yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\n\nexport function runCli(cwd: string, argv: string[]): void {\n const _ = yargs(hideBin(argv))\n .options({\n cwd: { type: 'string', default: cwd, describe: 'The current working directory', defaultDescription: '.' },\n verbose: { type: 'boolean', describe: 'If more output should be printed' },\n })\n .commandDir('commands')\n .demandCommand()\n .help()\n .parse();\n}\n"]}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Generates decentralized social network data in different phases.
3
+ */
4
+ export declare class Generator {
5
+ static readonly COLOR_RESET: string;
6
+ static readonly COLOR_RED: string;
7
+ static readonly COLOR_GREEN: string;
8
+ static readonly COLOR_YELLOW: string;
9
+ static readonly COLOR_BLUE: string;
10
+ static readonly COLOR_MAGENTA: string;
11
+ static readonly COLOR_CYAN: string;
12
+ static readonly COLOR_GRAY: string;
13
+ static readonly LDBC_SNB_DATAGEN_DOCKER_IMAGE: string;
14
+ private readonly cwd;
15
+ private readonly verbose;
16
+ private readonly overwrite;
17
+ private readonly scale;
18
+ private readonly enhancementConfig;
19
+ private readonly fragmentConfig;
20
+ private readonly queryConfig;
21
+ private readonly validationParams;
22
+ private readonly validationConfig;
23
+ private readonly hadoopMemory;
24
+ private readonly mainModulePath;
25
+ constructor(opts: IGeneratorOptions);
26
+ protected targetExists(path: string): Promise<boolean>;
27
+ protected log(phase: string, status: string): void;
28
+ protected runPhase(name: string, directory: string, runner: () => Promise<void>): Promise<void>;
29
+ /**
30
+ * Run all generator phases.
31
+ */
32
+ generate(): Promise<void>;
33
+ /**
34
+ * Invoke the LDBC SNB generator.
35
+ */
36
+ generateSnbDataset(): Promise<void>;
37
+ /**
38
+ * Enhance the generated LDBC SNB dataset.
39
+ */
40
+ enhanceSnbDataset(): Promise<void>;
41
+ /**
42
+ * Fragment the generated and enhanced LDBC SNB datasets.
43
+ */
44
+ fragmentSnbDataset(): Promise<void>;
45
+ /**
46
+ * Instantiate queries based on the LDBC SNB datasets.
47
+ */
48
+ instantiateQueries(): Promise<void>;
49
+ /**
50
+ * Download validation parameters
51
+ */
52
+ downloadValidationParams(): Promise<void>;
53
+ /**
54
+ * Generate validation queries and results.
55
+ */
56
+ generateValidation(): Promise<void>;
57
+ protected generateVariables(): Promise<Record<string, string>>;
58
+ /**
59
+ * Return a string in a given color
60
+ * @param str The string that should be printed in
61
+ * @param color A given color
62
+ */
63
+ static withColor(str: any, color: string): string;
64
+ }
65
+ export interface IGeneratorOptions {
66
+ cwd: string;
67
+ verbose: boolean;
68
+ overwrite: boolean;
69
+ scale: string;
70
+ enhancementConfig: string;
71
+ fragmentConfig: string;
72
+ queryConfig: string;
73
+ validationParams?: string;
74
+ validationConfig?: string;
75
+ hadoopMemory: string;
76
+ }
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Generator = void 0;
7
+ const promises_1 = require("node:fs/promises");
8
+ const node_https_1 = require("node:https");
9
+ const node_path_1 = require("node:path");
10
+ const dockerode_1 = __importDefault(require("dockerode"));
11
+ const ldbc_snb_enhancer_1 = require("ldbc-snb-enhancer");
12
+ const ldbc_snb_validation_generator_1 = require("ldbc-snb-validation-generator");
13
+ const rdf_dataset_fragmenter_1 = require("rdf-dataset-fragmenter");
14
+ const sparql_query_parameter_instantiator_1 = require("sparql-query-parameter-instantiator");
15
+ const unzipper_1 = require("unzipper");
16
+ /**
17
+ * Generates decentralized social network data in different phases.
18
+ */
19
+ class Generator {
20
+ constructor(opts) {
21
+ this.cwd = opts.cwd;
22
+ this.verbose = opts.verbose;
23
+ this.overwrite = opts.overwrite;
24
+ this.scale = opts.scale;
25
+ this.enhancementConfig = opts.enhancementConfig;
26
+ this.fragmentConfig = opts.fragmentConfig;
27
+ this.queryConfig = opts.queryConfig;
28
+ this.validationParams = opts.validationParams;
29
+ this.validationConfig = opts.validationConfig;
30
+ this.hadoopMemory = opts.hadoopMemory;
31
+ this.mainModulePath = (0, node_path_1.join)(__dirname, '..');
32
+ }
33
+ async targetExists(path) {
34
+ try {
35
+ await (0, promises_1.stat)(path);
36
+ return true;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ log(phase, status) {
43
+ process.stdout.write(`${Generator.withColor(`[${phase}]`, Generator.COLOR_CYAN)} ${status}\n`);
44
+ }
45
+ async runPhase(name, directory, runner) {
46
+ if (this.overwrite || !await this.targetExists((0, node_path_1.join)(this.cwd, directory))) {
47
+ this.log(name, 'Started');
48
+ const timeStart = process.hrtime();
49
+ await runner();
50
+ const timeEnd = process.hrtime(timeStart);
51
+ this.log(name, `Done in ${timeEnd[0] + (timeEnd[1] / 1_000_000_000)} seconds`);
52
+ }
53
+ else {
54
+ this.log(name, `Skipped (/${directory} already exists, remove to regenerate)`);
55
+ }
56
+ }
57
+ /**
58
+ * Run all generator phases.
59
+ */
60
+ async generate() {
61
+ const timeStart = process.hrtime();
62
+ await this.runPhase('SNB dataset generator', 'out-snb', () => this.generateSnbDataset());
63
+ await this.runPhase('SNB dataset enhancer', 'out-enhanced', () => this.enhanceSnbDataset());
64
+ await this.runPhase('SNB dataset fragmenter', 'out-fragments', () => this.fragmentSnbDataset());
65
+ await this.runPhase('SPARQL query instantiator', 'out-queries', () => this.instantiateQueries());
66
+ if (this.validationParams && this.validationConfig) {
67
+ await this.runPhase('SNB validation downloader', 'out-validate-params', () => this.downloadValidationParams());
68
+ await this.runPhase('SNB validation generator', 'out-validate', () => this.generateValidation());
69
+ }
70
+ const timeEnd = process.hrtime(timeStart);
71
+ this.log('All', `Done in ${timeEnd[0] + (timeEnd[1] / 1_000_000_000)} seconds`);
72
+ }
73
+ /**
74
+ * Invoke the LDBC SNB generator.
75
+ */
76
+ async generateSnbDataset() {
77
+ // Create params.ini file
78
+ const paramsTemplate = await (0, promises_1.readFile)((0, node_path_1.join)(__dirname, '../templates/params.ini'), 'utf8');
79
+ const paramsPath = (0, node_path_1.join)(this.cwd, 'params.ini');
80
+ await (0, promises_1.writeFile)(paramsPath, paramsTemplate.replaceAll('SCALE', this.scale), 'utf8');
81
+ // Pull the base Docker image
82
+ const dockerode = new dockerode_1.default();
83
+ const buildStream = await dockerode.pull(Generator.LDBC_SNB_DATAGEN_DOCKER_IMAGE);
84
+ await new Promise((resolve, reject) => {
85
+ dockerode.modem.followProgress(buildStream, (err, res) => err ? reject(err) : resolve(res));
86
+ });
87
+ // Start Docker container
88
+ const container = await dockerode.createContainer({
89
+ Image: Generator.LDBC_SNB_DATAGEN_DOCKER_IMAGE,
90
+ Tty: true,
91
+ AttachStdout: true,
92
+ AttachStderr: true,
93
+ Env: [`HADOOP_CLIENT_OPTS=-Xmx${this.hadoopMemory}`],
94
+ HostConfig: {
95
+ Binds: [
96
+ `${this.cwd}/out-snb/:/opt/ldbc_snb_datagen/out`,
97
+ `${paramsPath}:/opt/ldbc_snb_datagen/params.ini`,
98
+ ],
99
+ },
100
+ });
101
+ await container.start();
102
+ // Stop process on force-exit
103
+ let containerEnded = false;
104
+ // eslint-disable-next-line ts/no-misused-promises
105
+ process.on('SIGINT', async () => {
106
+ if (!containerEnded) {
107
+ await container.kill();
108
+ await cleanup();
109
+ }
110
+ });
111
+ async function cleanup() {
112
+ await container.remove();
113
+ await (0, promises_1.unlink)(paramsPath);
114
+ }
115
+ // Attach output to stdout
116
+ const out = await container.attach({
117
+ stream: true,
118
+ stdout: true,
119
+ stderr: true,
120
+ });
121
+ if (this.verbose) {
122
+ out.pipe(process.stdout);
123
+ }
124
+ else {
125
+ out.resume();
126
+ }
127
+ // Wait until generation ends
128
+ await new Promise((resolve, reject) => {
129
+ out.on('end', resolve);
130
+ out.on('error', reject);
131
+ });
132
+ containerEnded = true;
133
+ // Cleanup
134
+ await cleanup();
135
+ }
136
+ /**
137
+ * Enhance the generated LDBC SNB dataset.
138
+ */
139
+ async enhanceSnbDataset() {
140
+ // Create target directory
141
+ await (0, promises_1.mkdir)((0, node_path_1.join)(this.cwd, 'out-enhanced'));
142
+ // Run enhancer
143
+ const oldCwd = process.cwd();
144
+ process.chdir(this.cwd);
145
+ await (0, ldbc_snb_enhancer_1.runConfig)(this.enhancementConfig, { mainModulePath: this.mainModulePath });
146
+ process.chdir(oldCwd);
147
+ }
148
+ /**
149
+ * Fragment the generated and enhanced LDBC SNB datasets.
150
+ */
151
+ async fragmentSnbDataset() {
152
+ const oldCwd = process.cwd();
153
+ process.chdir(this.cwd);
154
+ // Initial fragmentation
155
+ await (0, rdf_dataset_fragmenter_1.runConfig)(this.fragmentConfig, { mainModulePath: this.mainModulePath });
156
+ process.chdir(oldCwd);
157
+ }
158
+ /**
159
+ * Instantiate queries based on the LDBC SNB datasets.
160
+ */
161
+ async instantiateQueries() {
162
+ // Create target directory
163
+ await (0, promises_1.mkdir)((0, node_path_1.join)(this.cwd, 'out-queries'));
164
+ // Run instantiator
165
+ const oldCwd = process.cwd();
166
+ process.chdir(this.cwd);
167
+ await (0, sparql_query_parameter_instantiator_1.runConfig)(this.queryConfig, { mainModulePath: this.mainModulePath }, {
168
+ variables: await this.generateVariables(),
169
+ });
170
+ process.chdir(oldCwd);
171
+ }
172
+ /**
173
+ * Download validation parameters
174
+ */
175
+ async downloadValidationParams() {
176
+ // Create target directory
177
+ const target = (0, node_path_1.join)(this.cwd, 'out-validate-params');
178
+ await (0, promises_1.mkdir)(target);
179
+ // Download and extract zip file
180
+ return new Promise((resolve, reject) => {
181
+ (0, node_https_1.request)(this.validationParams, (res) => {
182
+ res
183
+ .on('error', reject)
184
+ .pipe((0, unzipper_1.Extract)({ path: target }))
185
+ .on('error', reject)
186
+ .on('close', resolve);
187
+ }).end();
188
+ });
189
+ }
190
+ /**
191
+ * Generate validation queries and results.
192
+ */
193
+ async generateValidation() {
194
+ // Create target directory
195
+ await (0, promises_1.mkdir)((0, node_path_1.join)(this.cwd, 'out-validate'));
196
+ // Run generator
197
+ const oldCwd = process.cwd();
198
+ process.chdir(this.cwd);
199
+ await (0, ldbc_snb_validation_generator_1.runConfig)(this.validationConfig, { mainModulePath: this.mainModulePath }, {
200
+ variables: await this.generateVariables(),
201
+ });
202
+ process.chdir(oldCwd);
203
+ }
204
+ async generateVariables() {
205
+ const templateMappings = (await (0, promises_1.readdir)((0, node_path_1.join)(__dirname, '../templates/queries/')))
206
+ .map(name => [`urn:variables:query-templates:${name}`, (0, node_path_1.join)(__dirname, `../templates/queries/${name}`)]);
207
+ const refinementMappings = (await (0, promises_1.readdir)((0, node_path_1.join)(__dirname, '../templates/refinements/')))
208
+ .map(name => [`urn:variables:query-refinements:${name}`, (0, node_path_1.join)(__dirname, `../templates/refinements/${name}`)]);
209
+ const result = Object.fromEntries([...templateMappings, ...refinementMappings]);
210
+ return result;
211
+ }
212
+ /**
213
+ * Return a string in a given color
214
+ * @param str The string that should be printed in
215
+ * @param color A given color
216
+ */
217
+ static withColor(str, color) {
218
+ return `${color}${str}${Generator.COLOR_RESET}`;
219
+ }
220
+ }
221
+ exports.Generator = Generator;
222
+ Generator.COLOR_RESET = '\u001B[0m';
223
+ Generator.COLOR_RED = '\u001B[31m';
224
+ Generator.COLOR_GREEN = '\u001B[32m';
225
+ Generator.COLOR_YELLOW = '\u001B[33m';
226
+ Generator.COLOR_BLUE = '\u001B[34m';
227
+ Generator.COLOR_MAGENTA = '\u001B[35m';
228
+ Generator.COLOR_CYAN = '\u001B[36m';
229
+ Generator.COLOR_GRAY = '\u001B[90m';
230
+ Generator.LDBC_SNB_DATAGEN_DOCKER_IMAGE = 'rubensworks/ldbc_snb_datagen:latest';
231
+ //# sourceMappingURL=Generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Generator.js","sourceRoot":"","sources":["Generator.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat, unlink, mkdir, readdir, readFile, writeFile } from 'node:fs/promises';\nimport { request } from 'node:https';\nimport { join } from 'node:path';\nimport Dockerode from 'dockerode';\nimport { runConfig as runEnhancer } from 'ldbc-snb-enhancer';\nimport { runConfig as runValidationGenerator } from 'ldbc-snb-validation-generator';\nimport { runConfig as runFragmenter } from 'rdf-dataset-fragmenter';\nimport { runConfig as runQueryInstantiator } from 'sparql-query-parameter-instantiator';\nimport { Extract } from 'unzipper';\n\n/**\n * Generates decentralized social network data in different phases.\n */\nexport class Generator {\n public static readonly COLOR_RESET: string = '\\u001B[0m';\n public static readonly COLOR_RED: string = '\\u001B[31m';\n public static readonly COLOR_GREEN: string = '\\u001B[32m';\n public static readonly COLOR_YELLOW: string = '\\u001B[33m';\n public static readonly COLOR_BLUE: string = '\\u001B[34m';\n public static readonly COLOR_MAGENTA: string = '\\u001B[35m';\n public static readonly COLOR_CYAN: string = '\\u001B[36m';\n public static readonly COLOR_GRAY: string = '\\u001B[90m';\n public static readonly LDBC_SNB_DATAGEN_DOCKER_IMAGE: string = 'rubensworks/ldbc_snb_datagen:latest';\n\n private readonly cwd: string;\n private readonly verbose: boolean;\n private readonly overwrite: boolean;\n private readonly scale: string;\n private readonly enhancementConfig: string;\n private readonly fragmentConfig: string;\n private readonly queryConfig: string;\n private readonly validationParams: string | undefined;\n private readonly validationConfig: string | undefined;\n private readonly hadoopMemory: string;\n private readonly mainModulePath: string;\n\n public constructor(opts: IGeneratorOptions) {\n this.cwd = opts.cwd;\n this.verbose = opts.verbose;\n this.overwrite = opts.overwrite;\n this.scale = opts.scale;\n this.enhancementConfig = opts.enhancementConfig;\n this.fragmentConfig = opts.fragmentConfig;\n this.queryConfig = opts.queryConfig;\n this.validationParams = opts.validationParams;\n this.validationConfig = opts.validationConfig;\n this.hadoopMemory = opts.hadoopMemory;\n this.mainModulePath = join(__dirname, '..');\n }\n\n protected async targetExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n }\n\n protected log(phase: string, status: string): void {\n process.stdout.write(`${Generator.withColor(`[${phase}]`, Generator.COLOR_CYAN)} ${status}\\n`);\n }\n\n protected async runPhase(name: string, directory: string, runner: () => Promise<void>): Promise<void> {\n if (this.overwrite || !await this.targetExists(join(this.cwd, directory))) {\n this.log(name, 'Started');\n const timeStart = process.hrtime();\n await runner();\n const timeEnd = process.hrtime(timeStart);\n this.log(name, `Done in ${timeEnd[0] + (timeEnd[1] / 1_000_000_000)} seconds`);\n } else {\n this.log(name, `Skipped (/${directory} already exists, remove to regenerate)`);\n }\n }\n\n /**\n * Run all generator phases.\n */\n public async generate(): Promise<void> {\n const timeStart = process.hrtime();\n await this.runPhase('SNB dataset generator', 'out-snb', () => this.generateSnbDataset());\n await this.runPhase('SNB dataset enhancer', 'out-enhanced', () => this.enhanceSnbDataset());\n await this.runPhase('SNB dataset fragmenter', 'out-fragments', () => this.fragmentSnbDataset());\n await this.runPhase('SPARQL query instantiator', 'out-queries', () => this.instantiateQueries());\n if (this.validationParams && this.validationConfig) {\n await this.runPhase('SNB validation downloader', 'out-validate-params', () => this.downloadValidationParams());\n await this.runPhase('SNB validation generator', 'out-validate', () => this.generateValidation());\n }\n const timeEnd = process.hrtime(timeStart);\n this.log('All', `Done in ${timeEnd[0] + (timeEnd[1] / 1_000_000_000)} seconds`);\n }\n\n /**\n * Invoke the LDBC SNB generator.\n */\n public async generateSnbDataset(): Promise<void> {\n // Create params.ini file\n const paramsTemplate = await readFile(join(__dirname, '../templates/params.ini'), 'utf8');\n const paramsPath = join(this.cwd, 'params.ini');\n await writeFile(paramsPath, paramsTemplate.replaceAll('SCALE', this.scale), 'utf8');\n\n // Pull the base Docker image\n const dockerode = new Dockerode();\n const buildStream = await dockerode.pull(Generator.LDBC_SNB_DATAGEN_DOCKER_IMAGE);\n await new Promise((resolve, reject) => {\n dockerode.modem.followProgress(buildStream, (err: Error | null, res: any[]) => err ? reject(err) : resolve(res));\n });\n\n // Start Docker container\n const container = await dockerode.createContainer({\n Image: Generator.LDBC_SNB_DATAGEN_DOCKER_IMAGE,\n Tty: true,\n AttachStdout: true,\n AttachStderr: true,\n Env: [ `HADOOP_CLIENT_OPTS=-Xmx${this.hadoopMemory}` ],\n HostConfig: {\n Binds: [\n `${this.cwd}/out-snb/:/opt/ldbc_snb_datagen/out`,\n `${paramsPath}:/opt/ldbc_snb_datagen/params.ini`,\n ],\n },\n });\n await container.start();\n\n // Stop process on force-exit\n let containerEnded = false;\n // eslint-disable-next-line ts/no-misused-promises\n process.on('SIGINT', async() => {\n if (!containerEnded) {\n await container.kill();\n await cleanup();\n }\n });\n async function cleanup(): Promise<void> {\n await container.remove();\n await unlink(paramsPath);\n }\n\n // Attach output to stdout\n const out = await container.attach({\n stream: true,\n stdout: true,\n stderr: true,\n });\n if (this.verbose) {\n out.pipe(process.stdout);\n } else {\n out.resume();\n }\n\n // Wait until generation ends\n await new Promise((resolve, reject) => {\n out.on('end', resolve);\n out.on('error', reject);\n });\n containerEnded = true;\n\n // Cleanup\n await cleanup();\n }\n\n /**\n * Enhance the generated LDBC SNB dataset.\n */\n public async enhanceSnbDataset(): Promise<void> {\n // Create target directory\n await mkdir(join(this.cwd, 'out-enhanced'));\n\n // Run enhancer\n const oldCwd = process.cwd();\n process.chdir(this.cwd);\n await runEnhancer(this.enhancementConfig, { mainModulePath: this.mainModulePath });\n process.chdir(oldCwd);\n }\n\n /**\n * Fragment the generated and enhanced LDBC SNB datasets.\n */\n public async fragmentSnbDataset(): Promise<void> {\n const oldCwd = process.cwd();\n process.chdir(this.cwd);\n\n // Initial fragmentation\n await runFragmenter(this.fragmentConfig, { mainModulePath: this.mainModulePath });\n\n process.chdir(oldCwd);\n }\n\n /**\n * Instantiate queries based on the LDBC SNB datasets.\n */\n public async instantiateQueries(): Promise<void> {\n // Create target directory\n await mkdir(join(this.cwd, 'out-queries'));\n\n // Run instantiator\n const oldCwd = process.cwd();\n process.chdir(this.cwd);\n await runQueryInstantiator(this.queryConfig, { mainModulePath: this.mainModulePath }, {\n variables: await this.generateVariables(),\n });\n process.chdir(oldCwd);\n }\n\n /**\n * Download validation parameters\n */\n public async downloadValidationParams(): Promise<void> {\n // Create target directory\n const target = join(this.cwd, 'out-validate-params');\n await mkdir(target);\n\n // Download and extract zip file\n return new Promise((resolve, reject) => {\n request(this.validationParams!, (res) => {\n res\n .on('error', reject)\n .pipe(Extract({ path: target }))\n .on('error', reject)\n .on('close', resolve);\n }).end();\n });\n }\n\n /**\n * Generate validation queries and results.\n */\n public async generateValidation(): Promise<void> {\n // Create target directory\n await mkdir(join(this.cwd, 'out-validate'));\n\n // Run generator\n const oldCwd = process.cwd();\n process.chdir(this.cwd);\n await runValidationGenerator(this.validationConfig!, { mainModulePath: this.mainModulePath }, {\n variables: await this.generateVariables(),\n });\n process.chdir(oldCwd);\n }\n\n protected async generateVariables(): Promise<Record<string, string>> {\n const templateMappings: string[][] = (await readdir(join(__dirname, '../templates/queries/')))\n .map(name => [ `urn:variables:query-templates:${name}`, join(__dirname, `../templates/queries/${name}`) ]);\n const refinementMappings: string[][] = (await readdir(join(__dirname, '../templates/refinements/')))\n .map(name => [ `urn:variables:query-refinements:${name}`, join(__dirname, `../templates/refinements/${name}`) ]);\n const result = <Record<string, string>> Object.fromEntries([ ...templateMappings, ...refinementMappings ]);\n return result;\n }\n\n /**\n * Return a string in a given color\n * @param str The string that should be printed in\n * @param color A given color\n */\n public static withColor(str: any, color: string): string {\n return `${color}${str}${Generator.COLOR_RESET}`;\n }\n}\n\nexport interface IGeneratorOptions {\n cwd: string;\n verbose: boolean;\n overwrite: boolean;\n scale: string;\n enhancementConfig: string;\n fragmentConfig: string;\n queryConfig: string;\n validationParams?: string;\n validationConfig?: string;\n hadoopMemory: string;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Serves generated fragments over HTTP.
3
+ */
4
+ export declare class Server {
5
+ private readonly configPath;
6
+ private readonly port;
7
+ private readonly baseUrl;
8
+ private readonly rootFilePath;
9
+ private readonly logLevel;
10
+ constructor(options: IServerOptions);
11
+ serve(): Promise<void>;
12
+ }
13
+ export interface IServerOptions {
14
+ configPath: string;
15
+ port: number;
16
+ baseUrl: string | undefined;
17
+ rootFilePath: string;
18
+ logLevel: string;
19
+ }