-
Notifications
You must be signed in to change notification settings - Fork 0
/
presentation.html
1244 lines (1161 loc) · 99.7 KB
/
presentation.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui"><title>Crux Tutorial</title><link rel="stylesheet" href="reveal.js/css/reset.css"><link rel="stylesheet" href="reveal.js/css/reveal.css"><link rel="stylesheet" href="reveal.js/css/theme/black.css" id="theme"><!--This CSS is generated by the Asciidoctor reveal.js converter to further integrate AsciiDoc's existing semantic with reveal.js--><style type="text/css">.reveal div.right{float:right}
/* listing block */
.reveal .listingblock.stretch>.content{height: 100%}
.reveal .listingblock.stretch>.content>pre{height: 100%}
.reveal .listingblock.stretch>.content>pre>code{height:100%;max-height:100%}
/* tables */
table{border-collapse:collapse;border-spacing:0}
table{margin-bottom:1.25em;border:solid 1px #dedede}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
td.tableblock>.content{margin-bottom:1.25em}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot,table.frame-ends{border-width:1px 0}
.reveal table th.halign-left,.reveal table td.halign-left{text-align:left}
.reveal table th.halign-right,.reveal table td.halign-right{text-align:right}
.reveal table th.halign-center,.reveal table td.halign-center{text-align:center}
.reveal table th.valign-top,.reveal table td.valign-top{vertical-align:top}
.reveal table th.valign-bottom,.reveal table td.valign-bottom{vertical-align:bottom}
.reveal table th.valign-middle,.reveal table td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{font-weight:bold}
thead{display:table-header-group}
.reveal table.grid-none th,.reveal table.grid-none td{border-bottom:0!important}
/* kbd macro */
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
/* callouts */
.conum[data-value] {display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);-webkit-border-radius:50%;border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
/* Callout list */
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
/* Disabled from Asciidoctor CSS because it caused callout list to go under the
* source listing when .stretch is applied (see #335)
* .literalblock+.colist,.listingblock+.colist{margin-top:-.5em} */
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
/* Override Asciidoctor CSS that causes issues with reveal.js features */
.reveal .hljs table{border: 0}
/* Callout list rows would have a bottom border with some reveal.js themes (see #335) */
.reveal .colist>table th, .reveal .colist>table td {border-bottom:0}
/* Fixes line height with Highlight.js source listing when linenums enabled (see #331) */
.reveal .hljs table thead tr th, .reveal .hljs table tfoot tr th, .reveal .hljs table tbody tr td, .reveal .hljs table tr td, .reveal .hljs table tfoot tr td{line-height:inherit}
/* Columns layout */
.columns .slide-content {
display: flex;
}
.columns.wrap .slide-content {
flex-wrap: wrap;
}
.columns.is-vcentered .slide-content {
align-items: center;
}
.columns .slide-content > .column {
display: block;
flex-basis: 0;
flex-grow: 1;
flex-shrink: 1;
padding: .75rem;
}
.columns .slide-content > .column.is-full {
flex: none;
width: 100%;
}
.columns .slide-content > .column.is-four-fifths {
flex: none;
width: 80%;
}
.columns .slide-content > .column.is-three-quarters {
flex: none;
width: 75%;
}
.columns .slide-content > .column.is-two-thirds {
flex: none;
width: 66.6666%;
}
.columns .slide-content > .column.is-three-fifths {
flex: none;
width: 60%;
}
.columns .slide-content > .column.is-half {
flex: none;
width: 50%;
}
.columns .slide-content > .column.is-two-fifths {
flex: none;
width: 40%;
}
.columns .slide-content > .column.is-one-third {
flex: none;
width: 33.3333%;
}
.columns .slide-content > .column.is-one-quarter {
flex: none;
width: 25%;
}
.columns .slide-content > .column.is-one-fifth {
flex: none;
width: 20%;
}
</style><!--Printing and PDF exports--><script>var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? "reveal.js/css/print/pdf.css" : "reveal.js/css/print/paper.css";
document.getElementsByTagName( 'head' )[0].appendChild( link );</script></head><body><div class="reveal"><div class="slides"><section class="title" data-state="title"><h1>Crux Tutorial</h1><div class="preamble"><style>
.slide-background-content {
background: #353535;
}
.reveal h2 {
font-size: 1.6em;
color: #ffc85f;
}
.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .slide-content {
}
.reveal img, .reveal video, .reveal iframe {
height: 50vh;
}
.reveal section img {
margin: unset;
background: unset;
border: unset;
box-shadow: unset;
}
.reveal .comms blockquote {
font-family: Courier;
font-size: 2rem !important;
color: rgba(255, 176, 25, 0.90);
background: rgba(255, 255, 255, 0.05);
box-shadow: 0px 0px 10px rgba(255, 176, 25, 0.36);
font-style: unset;
text-align: justify;
width: unset;
}
.reveal code {
font-family: Monaco;
text-transform: none;
color: orange;
}
.reveal pre {
font-size: 2.5rem !important;
color: rgba(255, 176, 25, 0.90);
background: rgba(255, 255, 255, 0.05);
line-height: unset;
box-shadow: 0px 0px 10px rgba(255, 176, 25, 0.36);
}
.listingblock code {
font-size: .5em;
}
.manual .slide-content {
box-shadow: 0px 0px 10px rgba(255, 255, 255, 0.36);
background: black;
font-family: courier;
font-size: 0.7em;
overflow-y: auto;
height: 18em;
text-align: left;
padding: 1em;
width: unset;
}
.speech blockquote {
width: unset;
font-size: .75em;
height: 18em;
overflow: auto;
}
.language-clj {
}
.reveal pare code {
}
.manual {
}
.reveal blockquote {
}
.reveal blockquote p {
}
.comms {
}
.comms p {
}
.ticket {
background: white;
box-shadow: 10px 20px #F0000011;
height: 13em;
overflow: auto;
}
.ticket p, .ticket .hdlist1, .ticket .hdlist2, .ticket .title {
font-family: times;
font-size: 1.5rem;
color: #370000 !important;
}
</style></div></section>
<section><section id="_welcome"><h2>Welcome</h2></section><section id="_introduction"><h2>Introduction</h2><div class="slide-content"><div class="dlist"><dl><dt class="hdlist1">Johanna Antonelli</dt><dd><p><a href="mailto:[email protected]">[email protected]</a></p></dd></dl></div>
<aside class="notes"><div class="ulist"><ul><li><p>Joined JUXT as intern, full time year later after masters</p></li><li><p>Tutorial was first task</p></li></ul></div></aside></div></section><section id="_space_tutorial"><h2>Space Tutorial</h2><div class="slide-content"><div class="ulist"><ul><li><p>The space tutorial is designed as a gentle introduction to Crux.</p></li><li><p>Using basic Clojure</p></li><li><p>Choose your own adventure.. (debatable)</p></li></ul></div>
<aside class="notes"><div class="ulist"><ul><li><p>made to be a welcoming introduction to Crux</p></li><li><p>gentle introduction to basic concepts</p></li><li><p>basic clojure used</p></li></ul></div></aside></div></section><section id="_etiquette"><h2>Etiquette</h2><div class="slide-content"><div class="paragraph"><p>Technical questions at the end</p></div>
<aside class="notes"><div class="ulist"><ul><li><p>The tutorial aims to cover topics as standalone as can be.
This means a lot of questions may be answered as we progress.</p></li><li><p>Make a note.</p></li></ul></div></aside></div></section><section id="_any_questions_so_far"><h2>Any questions so far?</h2></section></section>
<section id="_mission"><h2>Mission</h2><div class="slide-content"><div class="paragraph"><p>Welcome to the year 2115</p></div>
<div class="paragraph"><p>Congratulations on your new position at Helios Banking Inc.</p></div>
<div class="ulist"><ul><li><p>Require juxt/crux as a dependency in your project</p></li></ul></div>
<aside class="notes"><div class="ulist"><ul><li><p>It’s the year 2115.</p></li><li><p>You have been hired by an inter-planetary bank, Helios Banking Inc.</p></li><li><p>Your task is to travel around the solar system completing assignments using Crux.</p></li><li><p>You have been given a Crux manual which will help you along your way.</p></li><li><p>In preparation you will have set up a project with crux as a dependency</p></li><li><p>instructions in the posts.</p></li></ul></div></aside></div></section>
<section><section id="_earth"><h2>Earth</h2><div class="slide-content"><div class="imageblock" style=""><img src="earth.png" alt="earth"></div></div></section><section id="_space_port"><h2>Space Port</h2><div class="slide-content"><div class="quoteblock comms"><blockquote><div class="paragraph"><p>A warm welcome from the Helios family.</p></div>
<div class="paragraph"><p>For your first assignment we would like you to go to Pluto and help Tombaugh Resources Ltd. set up their stock reporting system.</p></div>
<div class="paragraph"><p>Don’t forget to fill in your flight manifest, else you won’t be permitted entry to the planets.</p></div></blockquote></div></div></section><section id="_power_up"><h2>Power up</h2><div class="slide-content"><div class="paragraph"><p>Before you leave you must fill in your flight manifest.
To do this, you must first set up a Crux node.</p></div></div></section><section id="_crux_manual" class="manual"><h2>Crux Manual</h2><div class="slide-content"><div class="paragraph"><p>For a Clojure in-process node, the start-node function accepts a module tree, a file, or a resource.</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(require '[crux.api :as crux]
'[clojure.java.io :as io])
(crux/start-node {...}) ; module tree
(crux/start-node (io/file ...))
(crux/start-node (io/resource ...))</code></pre></div></div></div></section><section id="_start_node"><h2>Start node</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(require '[crux.api :as crux]
'[clojure.java.io :as io])
(def node
(crux/start-node
{:crux.node/topology '[crux.standalone/topology]
:crux.kv/db-dir "data/db-dir"}))</code></pre></div></div>
<aside class="notes"><div class="ulist"><ul><li><p>You want to get started as quickly as possible so you decide to use Crux’s inbuilt standalone node topology.</p></li><li><p>There is no persistence with this, so it is perfect for testing and debug.</p></li><li><p>Even so, Crux needs a database directory specified</p></li></ul></div></aside></div></section><section id="_flight_manifest"><h2>Flight manifest</h2><div class="slide-content"><div class="paragraph"><p>You take a look around your ship and check the critical levels.</p></div>
<div class="paragraph"><p>You read the manual entry for putting data into Crux.</p></div></div></section><section id="_crux_manual_2" class="manual"><h2>Crux manual</h2><div class="slide-content"><div class="paragraph"><p>Crux takes data in document form.
Each document must be in Extensible Data Notation (edn) and each document must contain a unique <code>:crux.db/id</code> value.
However, beyond those two requirements you have the flexibility to add whatever you like to your documents because Crux is schemaless.</p></div></div></section><section id="_flight_manifest_2"><h2>Flight Manifest</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(def manifest
{:crux.db/id :manifest
:pilot-name "Johanna"
:id/rocket "SB002-sol"
:id/employee "22910x2"
:badges "SETUP"
:cargo ["stereo" "gold fish" "slippers" "secret note"]})</code></pre></div></div>
<aside class="notes"><div class="ulist"><ul><li><p>Just as you’re about to write your manifest, one of the porters passes you a secret note and asks you to deliver it to a martian named Kaarlang.</p></li><li><p>They are certain you will meet Kaarlang on your travels and so you see no harm in delivering the note for them.</p></li></ul></div></aside></div></section><section id="_you_put_the_manifest_into_crux"><h2>You put the manifest into Crux.</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx node [[:crux.tx/put manifest]])
;;=>#:crux.tx{:tx-id 0, :tx-time #inst "2020-06-18T13:54:08.375-00:00"}</code></pre></div></div>
<div class="paragraph"><p>This is <code>put</code>, one of Crux’s four transaction operations.</p></div></div></section><section id="_check_entity_history"><h2>Check entity history</h2><div class="slide-content"><div class="paragraph"><p>Check that this was successful by asking Crux to show the entity history.</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/entity-history (crux/db node) :manifest :asc)
;;=> {:crux.tx/tx-time #inst "2020-06-18T13:54:08.375-00:00",
;; :crux.tx/tx-id 0,
;; :crux.db/valid-time #inst "2020-06-18T13:54:08.375-00:00",
;; :crux.db/content-hash #crux/id "0ab888b62775eea2eb2fffe10c9f6bfbf661a792"}</code></pre></div></div>
<aside class="notes"><div class="ulist"><ul><li><p>Which returns the history of the provided entity id at this point in time.</p></li><li><p>You can use <code>:asc</code> or <code>:desc</code> flag with entity-history for the ascending or descending history respectively.</p></li></ul></div></aside></div></section><section id="_liftoff"><h2>Liftoff!</h2></section></section>
<section><section id="_pluto"><h2>Pluto</h2><div class="slide-content"><div class="imageblock" style=""><img src="pluto.png" alt="pluto"></div><aside class="notes"><div class="ulist"><ul><li><p>As you enter the Plutonian atmosphere, a message pops up on your communication panel:</p></li></ul></div></aside></div></section><section id="_communications_panel"><h2>Communications panel</h2><div class="slide-content"><div class="quoteblock comms"><blockquote><div class="paragraph"><p>Welcome to the dwarf planet Pluto.
You are entering privately governed space.
If you do not have the correct papers, entry will be denied.
We hope you enjoy your stay.</p></div>
<div class="paragraph"><p>Have a nice day.</p></div>
<div class="paragraph"><p>— Anarchic Directorate of Pluto</p></div></blockquote></div>
<aside class="notes"><div class="paragraph"><p>The government of Pluto is asking to see your flight manifest.</p></div></aside></div></section><section id="_crux_manual_3" class="manual"><h2>Crux Manual</h2><div class="slide-content"><table class="tableblock frame-all grid-all" style="width:100%"><colgroup><col style="width:33.3333%"><col style="width:66.6667%"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Transaction</th><th class="tableblock halign-left valign-top">Description</th></tr><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>put</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Writes a version of a document</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>delete</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Deletes a version of a document</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>match</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Stops a transaction if the precondition is not met.</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>evict</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Removes a document entirely</p></td></tr></table>
<div class="paragraph"><p><strong>Put:</strong></p></div>
<div class="paragraph"><p>The <code>put</code> operation is used to write versions of a document (doc).</p></div>
<div class="paragraph"><p>Each document must be in <a href="https://opencrux.com/docs#tutorials-essential-edn">Extensible Data Notation</a> (edn) and must contain a unique <code>:crux.db/id</code> value.
However, beyond those two requirements you have the flexibility to add whatever you like to your documents because Crux is schemaless.</p></div>
<div class="paragraph"><p>Along with the document (doc), <code>put</code> has two optional additional arguments:</p></div>
<div class="hdlist"><table><tr><td class="hdlist1">start <code>valid-time</code> </td><td class="hdlist2"><p>The time at which the entry will be valid from.</p></td></tr><tr><td class="hdlist1">end <code>valid-time</code> </td><td class="hdlist2"><p>The time at which the entry will be valid until.</p></td></tr></table></div>
<div class="paragraph"><p>This means that you can query back through Crux, you can use <code>valid-time</code> arguments to see the state of Crux at a different time.</p></div>
<div class="paragraph"><p>If no <code>valid-time</code> is provided, start <code>valid-time</code> defaults to the transaction time and the document is valid either eternally or until the document is updated by a future transaction with the same eid.</p></div>
<div class="dlist"><dl><dt class="hdlist1">Time in Crux is denoted</dt><dd><p><code>#inst "yyyy-MM-ddThh:mm:SS"</code></p></dd><dt class="hdlist1">For example, 9:30 pm on January 2<sup>nd</sup> 1999 would be written: </dt><dd><p><code>#inst "1999-01-02T21:30:00"</code>.</p></dd><dt class="hdlist1">A complete <code>put</code> transaction has the form</dt><dd><p><code>[:crux.tx/put doc valid-time-start valid-time-end]</code></p></dd></dl></div>
<aside class="notes"><div class="ulist"><ul><li><p>Currently there are only four transaction operations in Crux: <code>put</code>, <code>delete</code>, <code>match</code> and <code>evict</code>.</p></li></ul></div></aside></div></section><section id="_ticket"><h2>Ticket</h2><div class="slide-content"><div class="openblock ticket"><div class="content"><div class="hdlist"><table><tr><td class="hdlist1">Task </td><td class="hdlist2"><p>Commodity Logging</p></td></tr><tr><td class="hdlist1">Company </td><td class="hdlist2"><p>Tombaugh Resources Ltd.</p></td></tr><tr><td class="hdlist1">Contact </td><td class="hdlist2"><p>R. Glogofloon</p></td></tr><tr><td class="hdlist1">Submitted </td><td class="hdlist2"><p>2115-02-20T13:38:20</p></td></tr><tr><td class="hdlist1">Additional information </td><td class="hdlist2"><p>We need help setting up a new recording system for our mine.
I have enclosed a list of the commodities we deal with.
Please send someone soon because we already have a week’s worth of unrecorded stock-takes.</p></td></tr><tr><td class="hdlist1">Attachments </td><td class="hdlist2"><p><a href="https://raw.githubusercontent.com/johantonelli/tutorials/master/tutorials.crux/resources/pluto.txt">TOMBAUGH-COMMOD_00ASD776a</a></p></td></tr></table></div></div></div>
<aside class="notes"><div class="paragraph"><p>You land on the surface of the dwarf planet.
As you do, the job ticket for this assignment is unlocked.</p></div></aside></div></section><section id="_assignment"><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx node
[[:crux.tx/put
{:crux.db/id :commodity/Pu
:common-name "Plutonium"
:type :element/metal
:density 19.816
:radioactive true}]
[:crux.tx/put
{:crux.db/id :commodity/N
:common-name "Nitrogen"
:type :element/gas
:density 1.2506
:radioactive false}]
[:crux.tx/put
{:crux.db/id :commodity/CH4
:common-name "Methane"
:type :molecule/gas
:density 0.717
:radioactive false}]])
;;=> #:crux.tx{:tx-id 0, :tx-time #inst "2020-06-18T14:11:51.087-00:00"}</code></pre></div></div>
<aside class="notes"><div class="ulist"><ul><li><p>You make your way over to the mines on the next shuttle.</p></li><li><p>On your way you decide to get a head start and put the commodities into Crux.</p></li><li><p>Since it takes six hours for each transaction to reach your Crux node on Earth from here, it is a good idea to batch up all the commodities in a single transaction.</p></li></ul></div></aside></div></section><section id="_stock_take"><h2>Stock take</h2><div class="slide-content"><div class="quoteblock speech"><blockquote><div class="paragraph"><p>Hello, I’m glad you’re here.</p></div>
<div class="paragraph"><p>I would like you to fill in our last week’s worth of data on our commodities.
We need to be able to look back at a given day and see what our stocks were for auditing purposes.</p></div>
<div class="paragraph"><p>The stock for each day must be submitted at 6pm Earth time (UTC) for your banks records.</p></div>
<div class="paragraph"><p>Are you able to do that for me?</p></div>
<div class="paragraph"><p>— R. Glogofloon</p></div></blockquote></div>
<aside class="notes"><div class="ulist"><ul><li><p>Reginald is asking if we can fill in the last weeks worth of data for their stocks.</p></li><li><p>He’s given us the valid time it needs to go in at for auditing purposes</p></li></ul></div></aside></div></section><section id="_input"><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">crux/submit-tx node
[[:crux.tx/put
{:crux.db/id :stock/Pu
:commod :commodity/Pu
:weight-ton 21 }
#inst "2115-02-13T18"] ;; valid-time
[:crux.tx/put
{:crux.db/id :stock/Pu
:commod :commodity/Pu
:weight-ton 23 }
#inst "2115-02-14T18"]
[:crux.tx/put
{:crux.db/id :stock/Pu
:commod :commodity/Pu
:weight-ton 22.2 }
#inst "2115-02-15T18"]
[:crux.tx/put
{:crux.db/id :stock/Pu
:commod :commodity/Pu
:weight-ton 24 }
#inst "2115-02-18T18"]
[:crux.tx/put
{:crux.db/id :stock/Pu
:commod :commodity/Pu
:weight-ton 24.9 }
#inst "2115-02-19T18"]])
;;=> #:crux.tx{:tx-id 1, :tx-time #inst "2020-06-18T14:14:08.347-00:00"}</code></pre></div></div></div></section><section id="_input_2"><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx node
[[:crux.tx/put
{:crux.db/id :stock/N
:commod :commodity/N
:weight-ton 3 }
#inst "2115-02-13T18" ;; start valid-time
#inst "2115-02-19T18"] ;; end valid-time
[:crux.tx/put
{:crux.db/id :stock/CH4
:commod :commodity/CH4
:weight-ton 92 }
#inst "2115-02-15T18"
#inst "2115-02-19T18"]])
;;=> #:crux.tx{:tx-id 2, :tx-time #inst "2020-06-18T14:15:19.716-00:00"}</code></pre></div></div>
<aside class="notes"><div class="paragraph"><p>You notice that the amount of Nitrogen and Methane has not changed in the last week which saves you some time</p></div></aside></div></section><section id="_result"><h2>Result</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/entity (crux/db node #inst "2115-02-14") :stock/Pu)
;;=> {:crux.db/id :stock/Pu, :commod :commodity/Pu, :weight-ton 21}
(crux/entity (crux/db node #inst "2115-02-18") :stock/Pu)
;;=> {:crux.db/id :stock/Pu, :commod :commodity/Pu, :weight-ton 22.2}</code></pre></div></div>
<aside class="notes"><div class="paragraph"><p>The CEO is impressed with your speed, but a little skeptical that you have done it properly.</p></div>
<div class="paragraph"><p>You gain their confidence by showing them the entries for Plutonium on two different days:</p></div></aside></div></section><section id="_easy_ingest"><h2>Easy ingest</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(defn easy-ingest
"Uses Crux put transaction to add a vector of documents to a node"
[node docs]
(crux/submit-tx node (mapv (fn [doc] [:crux.tx/put doc]) docs)))</code></pre></div></div>
<aside class="notes"><div class="paragraph"><p>As a parting gift to them you create an easy ingest function so that if they needed to add more commodities to their stock list they could do it fast.</p></div>
<div class="paragraph"><p>Tombaugh Resources Ltd. are happy that this will be simple enough to use. They thank you for the extra help and you head back to your ship.</p></div></aside></div></section><section id="_space_port_2"><h2>Space Port</h2><div class="slide-content"><div class="quoteblock comms"><blockquote><div class="paragraph"><p>Congratulations on completing your first assignment.</p></div>
<div class="paragraph"><p>We would like you to go to Mercury, the hub of the trade world.
Their main trade center has a new IT department and want you to show them how to query Crux.</p></div>
<div class="paragraph"><p>— Helios Banking Inc.</p></div></blockquote></div>
<aside class="notes"><div class="paragraph"><p>You are back at your ship and check your communications panel. There is a new assignment waiting for you:</p></div></aside></div></section><section id="_manifest"><h2>Manifest</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node
[[:crux.tx/put
(assoc manifest :badges ["SETUP" "PUT"])]])
;;=> #:crux.tx{:tx-id 3, :tx-time #inst "2020-06-18T14:20:31.602-00:00"}</code></pre></div></div>
<aside class="notes"><div class="paragraph"><p>It’s along flight so you refuel, and update your manifest.</p></div>
<div class="paragraph"><p>You have been awarded a new badge.</p></div>
<div class="paragraph"><p>The Clojure function assoc to save time.</p></div></aside></div></section><section id="_liftoff_2"><h2>Liftoff!</h2></section></section>
<section><section id="_mercury"><h2>Mercury</h2><div class="slide-content"><div class="imageblock" style=""><img src="mercury.png" alt="mercury"></div></div></section><section id="_communications_panel_2"><h2>Communications Panel</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You come into range of the satellites orbiting Mecury.</p></div>
<div class="paragraph"><p>Your communications panel lights up.</p></div>
<div class="paragraph"><p>The government is asking to see your flight manifest.</p></div>
<div class="paragraph"><p>You have permission to land</p></div></aside>
<div class="quoteblock comms"><blockquote><div class="paragraph"><p>Greetings.</p></div>
<div class="paragraph"><p>You have reached Mercury, home to the greatest stock market in the Solar System.
Your ship has been flagged as a transport vessel for business related activities.</p></div>
<div class="paragraph"><p>Please have your flight manifest ready and prepare to land.</p></div>
<div class="paragraph"><p>— Mercury Commonwealth</p></div></blockquote></div></div></section><section id="_space_port_3"><h2>Space Port</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You read your Crux manual as you wait for an available landing pad.</p></div></aside></div></section><section id="_crux_manual_4" class="manual"><h2>Crux Manual</h2><div class="slide-content"><div class="paragraph"><p>A Datalog query consists of a set of variables and a set of clauses.
The result of running a query is a result set (or lazy sequence) of the possible combinations of values that satisfy all of the clauses at the same time.
These combinations of values are referred to as "tuples".</p></div>
<div class="paragraph"><p>The possible values within the result tuples are derived from your database of documents.</p></div>
<div class="paragraph"><p>The documents themselves are represented in the database indexes as "entity–attribute–value" (EAV) facts.
For example, a single document</p></div>
<div class="paragraph"><p><code>{:crux.db/id :myid :color "blue" :age 12}</code></p></div>
<div class="paragraph"><p>is transformed into two facts</p></div>
<div class="paragraph"><p><code>[[:myid :color "blue"][:myid :age 12]]</code></p></div>
<div class="paragraph"><p>In the most basic case, a Datalog query works by searching for "subgraphs" in the database that match the pattern defined by the clauses. The values within these subgraphs are then returned according to the list of return variables requested in the :find vector within the query.</p></div></div></section><section id="_ticket_2"><h2>Ticket</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You land on the surface of the tidally locked planet. As you do, the job ticket for this assignment is issued.</p></div></aside>
<div class="openblock ticket"><div class="content"><div class="hdlist"><table><tr><td class="hdlist1">Task </td><td class="hdlist2"><p>Find information on products for stock buyers</p></td></tr><tr><td class="hdlist1">Company </td><td class="hdlist2"><p>Interplanetary Buyers & Sellers (IPBS)</p></td></tr><tr><td class="hdlist1">Contact </td><td class="hdlist2"><p>Cosmina Sinnett</p></td></tr><tr><td class="hdlist1">Submitted </td><td class="hdlist2"><p>2115-06-20T10:54:27</p></td></tr><tr><td class="hdlist1">Additional information </td><td class="hdlist2"><p>We have some new starters in the sales team. They need to be trained on how to query Crux using Datalog to quickly find the information they need on a product. Traders must have access to up-to-date information when talking to their clients. We would also like you to create a function that can be used for the things we have to look up a lot. I will include example data so they can learn using relevant commodities.</p></td></tr><tr><td class="hdlist1">Attachments </td><td class="hdlist2"><p>Attachments :: <a href="https://raw.githubusercontent.com/johantonelli/tutorials/master/tutorials.crux/resources/mercury.txt">example_data.txt</a></p></td></tr></table></div></div></div></div></section><section id="_attachment"><h2>Attachment</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>On your way over to the IPBS office you input the data in the attachment using the easy ingest function you created on Pluto. This means you are ready to give them a tutorial when you get there.</p></div></aside></div></section><section id="_cosmina"><div class="slide-content"><div class="quoteblock speech"><blockquote><div class="paragraph"><p>Oh good, you’re here.
I have a room reserved and we have five new starters ready and waiting to learn how to query Crux.</p></div>
<div class="paragraph"><p>We are in the middle of our double sunrise. The workers take this time to rest, but in half an Earth hour the sun will rise again and the workers will start back.</p></div>
<div class="paragraph"><p>You can take this time to prepare any training material if you wish.</p></div>
<div class="paragraph"><p>— Cosmina Sinnett, Head of Training - IPBS</p></div></blockquote></div>
<aside class="notes"><div class="paragraph"><p>You have the opportunity to prepare examples for the lesson ahead.</p></div></aside></div></section><section id="_lesson_plan"><h2>Lesson plan</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You put together examples and make notes so you can be confident in your lesson.</p></div></aside></div></section><section id="_lesson_1_basic_query"><h2>Lesson 1: Basic Query</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
'{:find [element]
:where [[element :type :element/metal]]})
;;=> #{[:commodity/Pu] [:commodity/Au]}</code></pre></div></div>
<aside class="notes"><div class="paragraph"><p>This basic query is returning all the elements that are defined as :element/metal. The :find clause tells Crux what variables you want to return.</p></div>
<div class="paragraph"><p>In this case we are returning the :crux.db/id due to our placement of element.</p></div></aside></div></section><section id="_lesson_2_quoting"><h2>Lesson 2: Quoting</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(=
(crux/q (crux/db node)
'{:find [element]
:where [[element :type :element/metal]]})
(crux/q (crux/db node)
{:find '[element]
:where '[[element :type :element/metal]]})
(crux/q (crux/db node)
(quote
{:find [element]
:where [[element :type :element/metal]]})))
;;=> true</code></pre></div></div>
<aside class="notes"><div class="paragraph"><p>The vectors given to the clauses should be quoted. How you do it at this stage is arbitrary, but it becomes more important if you are using :args, which we will cover momentarily.</p></div></aside></div></section><section id="_lesson_3_return_the_name_of_metal_elements"><h2>Lesson 3: Return the name of metal elements</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
'{:find [name]
:where [[e :type :element/metal]
[e :common-name name]]})
;;=> #{["Gold"] ["Plutonium"]}</code></pre></div></div>
<aside class="notes"><div class="paragraph"><p>To find all the names of the commodities that have a certain property, such as :type, you need to use a combination of clauses. Here we have bound the results of type :element/metal to e. Next, we can use the results bound to e and bind the :common-name of them to name. name is what has been specified to be returned and so our result is the common names of all the elements that are metals.</p></div>
<div class="paragraph"><p>One way to think of this is that you are filtering to only get the results that satisfy all the clauses.</p></div></aside></div></section><section id="_lesson_4_more_information"><h2>Lesson 4: More information</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
'{:find [name rho]
:where [[e :density rho]
[e :common-name name]]})
;;=> #{["Nitrogen" 1.2506] ["Carbon" 2.267] ["Methane" 0.717] ["Borax" 1.73] ["Gold" 19.3] ["Plutonium" 19.816]}</code></pre></div></div>
<aside class="notes"><div class="paragraph"><p>You can pull out as much data as you want into your result tuples by adding additional variables to the :find clause.</p></div>
<div class="paragraph"><p>The example above returns the :density and the :common-name values for all entities in Crux that have values of some kind for both :density and :common-name attributes.</p></div></aside></div></section><section id="_lesson_5_arguments"><h2>Lesson 5: Arguments</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
{:find '[name]
:where '[[e :type t]
[e :common-name name]]
:args [{'t :element/metal}]})
;;=> #{["Gold"] ["Plutonium"]}</code></pre></div></div>
<div class="paragraph"><p><code>:args</code> can be used to further filter the results. Lets break down what is going down here.</p></div></div></section><section id="_lesson_5_arguments_2"><h2>Lesson 5: Arguments</h2><div class="slide-content"><div class="paragraph"><p>First, we are assigning all <code>:crux.db/id</code> that have a <code>:type</code> to e:</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
{:find '[name]
:where '[[e :type t]
[e :common-name name]]
:args [{'t :element/metal}]})
;;=> #{["Gold"] ["Plutonium"]}</code></pre></div></div>
<div class="hdlist"><table><tr><td class="hdlist1"><code>e</code> </td><td class="hdlist2"><p>← <code>#{[:commodity/Pu] [:commodity/borax] [:commodity/CH4] [:commodity/Au] [:commodity/C] [:commodity/N]}</code></p></td></tr></table></div></div></section><section id="_lesson_5_arguments_3"><h2>Lesson 5: Arguments</h2><div class="slide-content"><div class="paragraph"><p>At the same time we are assigning all the :types to t:</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
{:find '[name]
:where '[[e :type t]
[e :common-name name]]
:args [{'t :element/metal}]})
;;=> #{["Gold"] ["Plutonium"]}</code></pre></div></div>
<div class="hdlist"><table><tr><td class="hdlist1"><code>t</code> </td><td class="hdlist2"><p>← <code>#{[:element/gas] [:element/metal] [:element/non-metal] [:mineral/solid] [:molecule/gas]}</code></p></td></tr></table></div></div></section><section id="_lesson_5_arguments_4"><h2>Lesson 5: Arguments</h2><div class="slide-content"><div class="paragraph"><p>Then we assign all the names within e that have a :common-name to name:</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
{:find '[name]
:where '[[e :type t]
[e :common-name name]]
:args [{'t :element/metal}]})
;;=> #{["Gold"] ["Plutonium"]}</code></pre></div></div>
<div class="hdlist"><table><tr><td class="hdlist1"><code>name</code> </td><td class="hdlist2"><p>← <code>#{["Methane"] ["Carbon"] ["Gold"] ["Plutonium"] ["Nitrogen"] ["Borax"]}</code></p></td></tr></table></div></div></section><section id="_lesson_5_arguments_5"><h2>Lesson 5: Arguments</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
{:find '[name]
:where '[[e :type t]
[e :common-name name]]
:args [{'t :element/metal}]})
;;=> #{["Gold"] ["Plutonium"]}</code></pre></div></div>
<div class="paragraph"><p>We have specified that we want to get the names out, but not before looking at :args</p></div>
<div class="paragraph"><p>In :args we have further filtered the results to only show us the names of that have :type :element/metal.</p></div>
<div class="paragraph"><p>We could have done that inside the :where clause, but using :args removes the need for hard-coding inside the query clauses.</p></div></div></section><section id="_lesson"><h2>Lesson</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You give your lesson to the new starters when they return. They are a good audience and follow it well.</p></div>
<div class="paragraph"><p>To check their understanding you set them a task to create a function to aid their daily queries. You are impressed with their efforts.</p></div>
<div class="paragraph"><p>When you are finished, Cosmina thanks you and you head back to the space port.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(defn filter-type
[type]
(crux/q (crux/db node)
{:find '[name]
:where '[[e :type t]
[e :common-name name]]
:args [{'t type}]}))
(defn filter-appearance
[description]
(crux/q (crux/db node)
{:find '[name IUPAC]
:where '[[e :common-name name]
[e :IUPAC-name IUPAC]
[e :appearance appearance]]
:args [{'appearance description}]}))
(filter-type :element/metal)
;;=> #{["Gold"] ["Plutonium"]}
(filter-appearance "white solid")
;;=> #{["Borax" "Sodium tetraborate decahydrate"]}</code></pre></div></div></div></section><section id="_space_port_4"><h2>Space Port</h2><div class="slide-content"><div class="paragraph"><p>You are back at your spaceship. Seeing another light on your communications panel, you realize there is another assignment ready for you.</p></div>
<div class="quoteblock comms"><blockquote><div class="paragraph"><p>Congratulations on completing your assignment. You are getting the hang of things now, and we are impressed with your progress.</p></div>
<div class="paragraph"><p>We would like you to go to Neptune.
They have recently lost a lot of data in a flood so they have decided to digitize their entire system and archives.
We told them you could do it in such a way that the data is still time ordered as it was with their previous filing system.</p></div>
<div class="paragraph"><p>Good luck, and don’t forget to update your manifest.</p></div>
<div class="paragraph"><p>— Banking Inc.</p></div></blockquote></div></div></section><section id="_manifest_2"><h2>Manifest</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You update your manifest with the latest badge.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node [[:crux.tx/put (assoc manifest
:badges ["SETUP" "PUT" "DATALOG-QUERIES"])]])
;;=> #:crux.tx{:tx-id 1, :tx-time #inst "2020-06-18T14:31:46.148-00:00"}</code></pre></div></div></div></section><section id="_liftoff_3"><h2>Liftoff!</h2></section></section>
<section><section id="_neptune"><h2>Neptune</h2><div class="slide-content"><div class="imageblock" style=""><img src="neptune.png" alt="neptune"></div></div></section><section id="_communications_panel_3"><h2>Communications panel</h2><div class="slide-content"><div class="quoteblock comms"><blockquote><div class="paragraph"><p>You enter the Neptunian atmosphere and your communications panel lights up.</p></div>
<div class="paragraph"><p>It is our honor to welcome you to the planet Neptune.</p></div>
<div class="paragraph"><p>If you are visiting for business reasons, please present your manifest.</p></div>
<div class="paragraph"><p>Otherwise, have your visa ready for inspection.</p></div>
<div class="paragraph"><p>— Poseidon Republic of Wealth</p></div></blockquote></div>
<aside class="notes"><div class="paragraph"><p>The government is asking to see your flight manifest.</p></div>
<div class="paragraph"><p>You have permission to land</p></div></aside></div></section><section id="_space_port_5"><h2>Space Port</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>On your way down to the landing site you take the time to read the Crux manual.</p></div></aside></div></section><section id="_crux_manual_5" class="manual"><h2>Crux Manual</h2><div class="slide-content"><div class="paragraph"><p>One or more documents can be inserted into Crux via a put transaction at a specific valid-time.
The valid-time can be any time (past, future or present).</p></div>
<div class="paragraph"><p>If no valid-time is provided, Crux will default to the transaction time, i.e. the present.
Each document survives until it is deleted or a new version of it is added.</p></div></div></section><section id="_assignment_2"><h2>Assignment</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Upon landing on the ice giant, your communications panel lights up indicating that the job ticket is available.</p></div></aside></div></section><section id="_ticket_3"><h2>Ticket</h2><div class="slide-content"><div class="openblock ticket"><div class="content"><div class="hdlist"><table><tr><td class="hdlist1">Task </td><td class="hdlist2"><p>Back fill insurance documents</p></td></tr><tr><td class="hdlist1">Company </td><td class="hdlist2"><p>Coast Insurance</p></td></tr><tr><td class="hdlist1">Contact </td><td class="hdlist2"><p>Lyndon Mercia-York</p></td></tr><tr><td class="hdlist1">Submitted </td><td class="hdlist2"><p>2115-02-22T13:38:20</p></td></tr><tr><td class="hdlist1">Additional information </td><td class="hdlist2"><p>We have lost a lot of our records in a flood.
I think it is prudent to start storing our data digitally.
It is important to track policy holders' level of cover at the time of the incident.
We have read a lot about the conveniences of Crux’s bitemporality in this situation.
We need you to help us get up and running.
Please send someone quickly though - the waters are rising.</p></td></tr><tr><td class="hdlist1">Attachments </td><td class="hdlist2"><p> — </p></td></tr></table></div></div></div></div></section><section id="_lyndon"><div class="slide-content"><div class="quoteblock speech"><blockquote><div class="paragraph"><p>Thank goodness you’re here.</p></div>
<div class="paragraph"><p>We need you to show us how to put our customers information into Crux in order of time. Working with insurance claims, we should be able to easily look back in time at what type of coverage the customer had at the time of the incident.</p></div>
<div class="paragraph"><p>Are you able to help us?</p></div>
<div class="paragraph"><p>— Lyndon Mercia-York</p></div></blockquote></div>
<aside class="notes"><div class="paragraph"><p>Outside your ship you are met by a panicked looking Lyndon.</p></div></aside></div></section><section id="_ingestion"><h2>Ingestion</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Lyndon gives you some data for a client that you can use as an example.
Coast Insurance need to know what kind of cover each customer has and if it was valid at a given time.</p></div>
<div class="paragraph"><p>You show them how to ingest a document using a valid-time so that the information is backdated to when the customer took the cover out.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node
[[:crux.tx/put
{:crux.db/id :consumer/RJ29sUU
:consumer-id :RJ29sUU
:first-name "Jay"
:last-name "Rose"
:cover? true
:cover-type :Full}
#inst "2114-12-03"]])
;;=> #:crux.tx{:tx-id 0, :tx-time #inst "2020-06-18T14:38:29.240-00:00"}</code></pre></div></div></div></section><section id="_bitemporality"><h2>Bitemporality</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>The company needs to know the history of insurance for each cover. You show them how to use the bitemporality of Crux to do this.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node
[[:crux.tx/put (1)
{:crux.db/id :consumer/RJ29sUU
:consumer-id :RJ29sUU
:first-name "Jay"
:last-name "Rose"
:cover? true
:cover-type :Full}
#inst "2113-12-03" ;; Valid time start
#inst "2114-12-03"] ;; Valid time end
[:crux.tx/put (2)
{:crux.db/id :consumer/RJ29sUU
:consumer-id :RJ29sUU
:first-name "Jay"
:last-name "Rose"
:cover? true
:cover-type :Full}
#inst "2112-12-03"
#inst "2113-12-03"]
[:crux.tx/put (3)
{:crux.db/id :consumer/RJ29sUU
:consumer-id :RJ29sUU
:first-name "Jay"
:last-name "Rose"
:cover? false}
#inst "2112-06-03"
#inst "2112-12-02"]
[:crux.tx/put (4)
{:crux.db/id :consumer/RJ29sUU
:consumer-id :RJ29sUU
:first-name "Jay"
:last-name "Rose"
:cover? true
:cover-type :Promotional}
#inst "2111-06-03"
#inst "2112-06-03"]])
;;=> #:crux.tx{:tx-id 1, :tx-time #inst "2020-06-18T14:39:11.189-00:00"}</code></pre></div></div>
<aside class="notes"><div class="olist arabic"><ol class="arabic"><li><p>This is the insurance that the customer had last year. Along with the start valid-time you use an end valid-time so as not to affect the most recent version of the document.</p></li><li><p>This is the previous insurance plan. Again, you use a start and end valid-time.</p></li><li><p>There was a period when the customer was not covered,</p></li><li><p>and before that the customer was on a promotional plan.</p></li></ol></div></aside></div></section><section id="_queries_through_time"><h2>Queries through time</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You now show them a few queries.
You know that you can query Crux as of a given valid-time.
This shows the state of Crux at that time.</p></div></aside>
<div class="paragraph"><p>First you chose a date that the customer had full cover:</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node #inst "2115-07-03")
'{:find [cover type]
:where [[e :consumer-id :RJ29sUU]
[e :cover? cover]
[e :cover-type type]]})
;;=> #{[true :Full]}</code></pre></div></div></div></section><section id="_queries_through_time_2"><h2>Queries through time</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Next you show them a query for a the customer in a time when they had a different type of cover:</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node #inst "2111-07-03")
'{:find [cover type]
:where [[e :consumer-id :RJ29sUU]
[e :cover? cover]
[e :cover-type type]]})
;;=> #{[true :Promotional]}</code></pre></div></div></div></section><section id="_queries_through_time_3"><h2>Queries through time</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>And finally you show them a time when the customer had no cover at all.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node #inst "2112-07-03")
'{:find [cover type]
:where [[e :consumer-id :RJ29sUU]
[e :cover? cover]
[e :cover-type type]]})
;;=> #{}</code></pre></div></div></div></section><section id="_lyndon_2"><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Confident in their ability to put the remainder of their records into Crux, Lyndon thanks you.</p></div>
<div class="paragraph"><p>You say goodbye to Lyndon and head back to the space port.</p></div></aside>
<div class="quoteblock speech"><blockquote><div class="paragraph"><p>I can’t believe we’ve not digitized sooner. There was a huge push to start using more paper as the Neptune tree population was getting out of control from the accelerated terraforming, but since all these floods I’m not sure paper was the right choice.</p></div>
<div class="paragraph"><p>— Lyndon Mercia-York</p></div></blockquote></div></div></section><section id="_space_port_6"><h2>Space Port</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Back at your spaceship you check your communications panel. There is a new assignment waiting for you.</p></div></aside></div></section><section id="_communications_pannel"><h2>Communications Pannel</h2><div class="slide-content"><div class="quoteblock comms"><blockquote><div class="paragraph"><p>We have assigned you a quick task on Saturn helping a small company who are having some problems keeping their records in order.</p></div>
<div class="paragraph"><p>This shouldn’t take long, but don’t forget they will still need to see your manifest.</p></div>
<div class="paragraph"><p>— Helios Banking Inc.</p></div></blockquote></div></div></section><section id="_update_manifest"><h2>Update Manifest</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You add the new badge to your manifest</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node [[:crux.tx/put
(assoc manifest
:badges ["SETUP" "PUT" "DATALOG-QUERIES" "BITEMP"])]])
;;=> #:crux.tx{:tx-id 2, :tx-time #inst "2020-06-18T14:46:47.606-00:00"}</code></pre></div></div></div></section><section id="_liftoff_4"><h2>Liftoff!</h2></section></section>
<section><section id="_saturn"><h2>Saturn</h2><div class="slide-content"><div class="imageblock" style=""><img src="saturn.png" alt="saturn"></div></div></section><section id="_communications_panel_4"><h2>Communications Panel</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>As you pass through the innermost ring of Saturn, A warning light appears on your communications panel.
You open the message.
It’s from Space Customs and reads:</p></div>
<div class="paragraph"><p>They are asking to see your flight manifest.</p></div>
<div class="paragraph"><p>You have permission to land</p></div></aside>
<div class="quoteblock comms"><blockquote><div class="paragraph"><p>We extend you the warmest welcome.</p></div>
<div class="paragraph"><p>We must check papers before we can give you permission to land.</p></div>
<div class="paragraph"><p>— Cronus Peaceful Nations</p></div></blockquote></div></div></section><section id="_space_port_7"><h2>Space Port</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>As you prepare to land you open your Crux manual to the page on match.</p></div></aside></div></section><section id="_crux_manual_6" class="manual"><h2>Crux Manual</h2><div class="slide-content"><table class="tableblock frame-all grid-all" style="width:100%"><colgroup><col style="width:33.3333%"><col style="width:66.6667%"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Transaction</th><th class="tableblock halign-left valign-top">Description</th></tr><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>put</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Writes a version of a document</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>delete</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Deletes a version of a document</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>match</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Stops a transaction if the precondition is not met.</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>evict</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Removes a document entirely</p></td></tr></table>
<div class="paragraph"><div class="title"><strong>match:</strong></div><p><code>match</code> checks the current state of an entity - if the entity doesn’t match the provided doc, the transaction will not continue.
You can also pass nil to check that the entity doesn’t exist prior to your transaction.</p></div>
<div class="paragraph"><p>A match transaction takes the entity id, along with an expected document.
Optionally you can provide a valid time.</p></div>
<div class="dlist"><dl><dt class="hdlist1">Time in Crux is denoted</dt><dd><p><code>#inst "yyyy-MM-ddThh:mm:SS"</code></p></dd><dt class="hdlist1">For example, 9:30 pm on January 2<sup>nd</sup> 1999 would be written: </dt><dd><p><code>#inst "1999-01-02T21:30:00"</code>.</p></dd><dt class="hdlist1">A complete match transaction has the form</dt><dd><p><code>[:crux.tx/match entity-id expected-doc valid-time]</code></p></dd></dl></div></div></section><section id="_assignment_3"><h2>Assignment</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>As you land on the surface of Saturn the job ticket for this assignment is unlocked.</p></div></aside></div></section><section id="_ticket_4"><h2>Ticket</h2><div class="slide-content"><div class="openblock ticket"><div class="content"><div class="hdlist"><table><tr><td class="hdlist1">Task </td><td class="hdlist2"><p>Secure trading system</p></td></tr><tr><td class="hdlist1">Company </td><td class="hdlist2"><p>Cronus Market Technologies</p></td></tr><tr><td class="hdlist1">Contact </td><td class="hdlist2"><p>Ubuku Eppimami</p></td></tr><tr><td class="hdlist1">Submitted </td><td class="hdlist2"><p>2115-02-23T13:38:20</p></td></tr><tr><td class="hdlist1">Additional information </td><td class="hdlist2"><p>We need to be shown how to ensure no trades are done without the buyer and seller having the necessary funds or stock respectively</p></td></tr><tr><td class="hdlist1">Attachments </td><td class="hdlist2"><p><a href="https://raw.githubusercontent.com/johantonelli/tutorials/master/tutorials.crux/resources/saturn.txt">example_data</a></p></td></tr></table></div></div></div></div></section><section id="_ingest"><h2>Ingest</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>The next shuttle to the CMT office leaves in 5 Earth minutes. While you wait you use your easy ingest function you created on Pluto to put the example data into your system. You also decide to make some Clojure functions so you can easily show Ubuku the stock and fund levels after the trades.</p></div>
<div class="paragraph"><p>Just as you are finishing off your shuttle arrives.</p></div>
<div class="paragraph"><p>After a short journey through the icy lower clouds of Saturn you are met by a friendly faced Ubuku.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(defn stock-check
[company-id item]
{:result (crux/q (crux/db node)
{:find '[name funds stock]
:where ['[e :company-name name]
'[e :credits funds]
['e item 'stock]]
:args [{'e company-id}]})
:item item})
(defn format-stock-check
[{:keys [result item] :as stock-check}]
(for [[name funds commod] result]
(str "Name: " name ", Funds: " funds ", " item " " commod)))</code></pre></div></div></div></section><section id="_ubuku"><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You explain to Ubuku that all they need to do to solve their problem is to use the match operation along with put when they are processing their trades.</p></div></aside>
<div class="quoteblock speech"><blockquote><div class="paragraph"><p>Hello friend.</p></div>
<div class="paragraph"><p>We have been using Crux for a short time now and think it is great. The problem is a human one. Occasionally we process trades without checking that are enough funds in the buyers account.</p></div>
<div class="paragraph"><p>I know there is a way that we can stop this happening in Crux.</p></div>
<div class="paragraph"><p>I sent you some example data in the job ticket for you to use, did you find it alright?</p></div>
<div class="paragraph"><p>— Ubuku Eppimami</p></div></blockquote></div></div></section><section id="_match"><h2>Match</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You show Ubuku the match operation for a valid transaction. You move 10 units of Methane (:units/CH4) each at the cost of 100 credits to Blue Energy:</p></div>
<div class="paragraph"><p>You explain that because the provided doc is as expected for both the buyer and the seller that the transaction goes through.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node
[[:crux.tx/match
:blue-energy
{:crux.db/id :blue-energy
:seller? false
:buyer? true
:company-name "Blue Energy"
:credits 1000}]
[:crux.tx/put
{:crux.db/id :blue-energy
:seller? false
:buyer? true
:company-name "Blue Energy"
:credits 900
:units/CH4 10}]
[:crux.tx/match
:tombaugh-resources
{:crux.db/id :tombaugh-resources
:company-name "Tombaugh Resources Ltd."
:seller? true
:buyer? false
:units/Pu 50
:units/N 3
:units/CH4 92
:credits 51}]
[:crux.tx/put
{:crux.db/id :tombaugh-resources
:company-name "Tombaugh Resources Ltd."
:seller? true
:buyer? false
:units/Pu 50
:units/N 3
:units/CH4 82
:credits 151}]])
;;=> #:crux.tx{:tx-id 0, :tx-time #inst "2020-06-18T15:37:20.271-00:00"}</code></pre></div></div></div></section><section id="_result_2"><h2>Result</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You show Ubuku the result of the trade using the function you created earlier:</p></div>
<div class="paragraph"><p>They are happy that this works as he sees the 1000 credits move from Blue energy to Tombaugh Resources Ltd. and 10 units of Methane the other way.</p></div>
<div class="paragraph"><p>Ubuku asks if you can show them what would happen if there was not enough funds in the account of a buyer.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(format-stock-check (stock-check :tombaugh-resources :units/CH4))
;;=> ("Name: Tombaugh Resources Ltd., Funds: 151, :units/CH4 82")</code></pre></div></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(format-stock-check (stock-check :blue-energy :units/CH4))
;;=> ("Name: Blue Energy, Funds: 900, :units/CH4 10")</code></pre></div></div></div></section><section id="_match_2"><h2>Match</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You show him a trade where the old doc is not as expected for Encompass trade, to buy 10,000 units of Gold from Gold Harmony.</p></div>
<div class="paragraph"><p>You explain to Ubuku that this time, because you have both match operations in the same transaction, the trade does not go through.</p></div>
<div class="paragraph"><p>The accounts remain the same, even though the failing match was the second operation.</p></div>
<div class="paragraph"><p>Ubuku thanks you. This is just what they are looking for. You head back to the space station to see if there is another assignment waiting for you.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node
[[:crux.tx/match
:gold-harmony
{:crux.db/id :gold-harmony
:company-name "Gold Harmony"
:seller? true
:buyer? false
:units/Au 10211
:credits 51}]
[:crux.tx/put
{:crux.db/id :gold-harmony
:company-name "Gold Harmony"
:seller? true
:buyer? false
:units/Au 211
:credits 51}]
[:crux.tx/match
:encompass-trade
{:crux.db/id :encompass-trade
:company-name "Encompass Trade"
:seller? true
:buyer? true
:units/Au 10
:units/Pu 5
:units/CH4 211
:credits 100002}]
[:crux.tx/put
{:crux.db/id :encompass-trade
:company-name "Encompass Trade"
:seller? true
:buyer? true
:units/Au 10010
:units/Pu 5
:units/CH4 211
:credits 1002}]])
;;=> #:crux.tx{:tx-id 1, :tx-time #inst "2020-06-18T15:23:38.540-00:00"}
(format-stock-check (stock-check :gold-harmony :units/Au))
;;=> ("Name: Gold Harmony, Funds: 51, :units/Au 10211")
(format-stock-check (stock-check :encompass-trade :units/Au))
;;=> ("Name: Encompass Trade, Funds: 1002, :units/Au 10")</code></pre></div></div></div></section><section id="_space_port_8"><h2>Space Port</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Back at the spaceship there is a light waiting for you on your communications panel.</p></div></aside>
<div class="quoteblock comms"><blockquote><div class="paragraph"><p>Well done, you’ve had a productive week. We have one final task for you to do before you finish for the week</p></div>
<div class="paragraph"><p>You need to go to Jupiter and meet Kaarlang, it’s his last day working for us and he needs to delete his trade clients from his personal Crux node for data protection.</p></div>
<div class="paragraph"><p>— Helios Banking Inc.</p></div></blockquote></div></div></section><section id="_update_manifest_2"><h2>Update Manifest</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You update your manifest with your most recent badge.</p></div>
<div class="paragraph"><p>As you do so, you check to see if you still have the note that the porter gave you for Kaarlang back on Earth.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node [[:crux.tx/put
(assoc manifest
:badges ["SETUP" "PUT" "DATALOG-QUERIES" "BITEMP" "MATCH"])]])
;;=> #:crux.tx{:tx-id 3, :tx-time #inst "2020-06-18T15:24:39.037-00:00"}</code></pre></div></div></div></section><section id="_update_manifest_3"><h2>Update Manifest</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/q (crux/db node)
{:find '[belongings]
:where '[[e :cargo belongings]]
:args [{'belongings "secret note"}]})
;;=> #{["secret note"]}</code></pre></div></div></div></section><section id="_liftoff_5"><h2>Liftoff!</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Feeling a bit apprehensive, you enter countdown for lift off to Jupiter. See you soon.</p></div></aside></div></section></section>
<section><section id="_jupiter"><h2>Jupiter</h2><div class="slide-content"><div class="imageblock" style=""><img src="jupiter.png" alt="jupiter"></div><aside class="notes"><div class="paragraph"><p>You approach Jupiter and marvel at its bands.
You wish you could have seen it this close before the Great Red Spot dissipated.</p></div>
<div class="paragraph"><p>As you enter the Jovian atmosphere your communications panel lights up with the now expected, but rather terse message from boundary control.</p></div></aside></div></section><section id="_communications_panel_5"><h2>Communications Panel</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>The government is asking to see your flight manifest.</p></div>
<div class="paragraph"><p>You have your manifest ready and so have permission to land</p></div></aside>
<div class="quoteblock comms"><blockquote><div class="paragraph"><p>Jupiter’s boundary is controlled.</p></div>
<div class="paragraph"><p>If you wish to enter, present your papers now.</p></div>
<div class="paragraph"><p>— Zeus Confederacy</p></div></blockquote></div></div></section><section id="_space_port_9"><h2>Space Port</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>It’s a turbulent ride down to the space port.
To take your mind off the colossal storm outside, you check the Crux manual for the <code>delete</code> operation.</p></div></aside></div></section><section id="_crux_manual_7" class="manual"><h2>Crux Manual</h2><div class="slide-content"><table class="tableblock frame-all grid-all" style="width:100%"><colgroup><col style="width:33.3333%"><col style="width:66.6667%"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Operation</th><th class="tableblock halign-left valign-top">Description</th></tr><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>put</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Writes a version of a document</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>delete</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Deletes a version of a document</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>match</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Stops a transaction if the precondition is not met.</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>evict</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Removes a document entirely</p></td></tr></table>
<div class="paragraph"><p><strong>Delete:</strong></p></div>
<div class="paragraph"><p>The <code>delete</code> operation takes a valid eid with the option to include a start and end <code>valid-time</code>.</p></div>
<div class="dlist"><dl><dt class="hdlist1">Time in Crux is denoted</dt><dd><p><code>#inst "yyyy-MM-ddThh:mm:SS"</code></p></dd><dt class="hdlist1">For example, 9:30 pm on January 2<sup>nd</sup> 1999 would be written: </dt><dd><p><code>#inst "1999-01-02T21:30:00"</code>.</p></dd></dl></div>
<div class="paragraph"><p>The document will be deleted as of the transaction time, or between the start and end <code>valid-time</code> if provided.
Historical versions of the document that fall outside of the <code>valid-time</code> window will be preserved.</p></div>
<div class="dlist"><dl><dt class="hdlist1">A complete delete transaction has the form</dt><dd><p><code>[:crux.tx/delete eid valid-time-start valid-time-end]</code></p></dd></dl></div></div></section><section id="_assignment_4"><h2>Assignment</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You land on the raised platform and open your job ticket:</p></div></aside></div></section><section id="_ticket_5"><h2>Ticket</h2><div class="slide-content"><div class="openblock ticket"><div class="content"><div class="hdlist"><table><tr><td class="hdlist1">Task </td><td class="hdlist2"><p><code>Remove assigned clients for leaver.</code></p></td></tr><tr><td class="hdlist1">Company </td><td class="hdlist2"><p><code>Helios Banking Inc.</code></p></td></tr><tr><td class="hdlist1">Contact </td><td class="hdlist2"><p><code>Kaarlang</code></p></td></tr><tr><td class="hdlist1">Submitted </td><td class="hdlist2"><p><code>2115-02-10T13:38:20</code></p></td></tr><tr><td class="hdlist1">Additional information </td><td class="hdlist2"><p><code>Help Kaarlang delete client history from his Crux node in accordance with Earth data protection laws.</code></p></td></tr><tr><td class="hdlist1">Attachments </td><td class="hdlist2"><p> — </p></td></tr></table></div></div></div></div></section><section id="_kaarlang"><div class="slide-content"><aside class="notes"><div class="paragraph"><p>As you leave your ship, you are met by the martian Kaarlang:</p></div>
<div class="paragraph"><p>Yes, we’ll work together to do this.</p></div>
<div class="paragraph"><p>Kaarlang gives you his client history so you can sync up your Crux node.</p></div></aside>
<div class="quoteblock speech"><blockquote><div class="paragraph"><p>Hi there, I believe you’re here to help me.</p></div>
<div class="paragraph"><p>I’ve been told I need to delete my client history with today being my last day.</p></div>
<div class="paragraph"><p>Is this something you can help me with?</p></div></blockquote></div></div></section><section id="_ingest_2"><h2>Ingest</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You input the client history</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node [[:crux.tx/put {:crux.db/id :kaarlang/clients
:clients [:encompass-trade]}
#inst "2110-01-01T09"
#inst "2111-01-01T09"]
[:crux.tx/put {:crux.db/id :kaarlang/clients
:clients [:encompass-trade :blue-energy]}
#inst "2111-01-01T09"
#inst "2113-01-01T09"]
[:crux.tx/put {:crux.db/id :kaarlang/clients
:clients [:blue-energy]}
#inst "2113-01-01T09"
#inst "2114-01-01T09"]
[:crux.tx/put {:crux.db/id :kaarlang/clients
:clients [:blue-energy :gold-harmony :tombaugh-resources]}
#inst "2114-01-01T09"
#inst "2115-01-01T09"]])
;;=> #:crux.tx{:tx-id 0, :tx-time #inst "2020-06-18T15:55:00.894-00:00"}</code></pre></div></div></div></section><section id="_delete"><h2>Delete</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>To get a good visual aid, you show Kaarlang how to view his client history.
This way you both can see when the clients are deleted.
You use the option <code>:with-docs?</code> to show the content of the doc.</p></div>
<div class="paragraph"><p>The result shows the names of the clients that have been assigned to Kaarlang since he started at the company in 2110.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/entity-history
(crux/db node #inst "2116-01-01T09")
:kaarlang/clients
:desc
{:with-docs? true})
#_#_
=> [{:crux.tx/tx-time #inst "2020-06-18T15:57:28.900-00:00",
:crux.tx/tx-id 1,
:crux.db/valid-time #inst "2114-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "d4bca6c78409d9d40ee42319a8aec32bffad9030",
:crux.db/doc
{:crux.db/id :kaarlang/clients,
:clients [:blue-energy :gold-harmony :tombaugh-resources]}}
{:crux.tx/tx-time #inst "2020-06-18T15:57:28.900-00:00",
:crux.tx/tx-id 1,
:crux.db/valid-time #inst "2113-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "000e5b775b55d06f0bddc77d736184284aa1e4e9",
:crux.db/doc {:crux.db/id :kaarlang/clients, :clients [:blue-energy]}}
{:crux.tx/tx-time #inst "2020-06-18T15:57:28.900-00:00",
:crux.tx/tx-id 1,
:crux.db/valid-time #inst "2111-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "cd71551fe21219db59067ce7483370fdebaae8b0",
:crux.db/doc
{:crux.db/id :kaarlang/clients, :clients [:encompass-trade :blue-energy]}}
{:crux.tx/tx-time #inst "2020-06-18T15:57:28.900-00:00",
:crux.tx/tx-id 1,
:crux.db/valid-time #inst "2110-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "5ec42ea653288e01e1a9d7d2068b4658416177e0",
:crux.db/doc {:crux.db/id :kaarlang/clients, :clients [:encompass-trade]}}]</code></pre></div></div></div></section><section id="_delete_2"><h2>Delete</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Next you delete the whole history of clients buy choosing a start and end <code>valid-time</code> that spans his entire employment time.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx
node [[:crux.tx/delete :kaarlang/clients #inst "2110-01-01" #inst "2116-01-01"]])
;;=> #:crux.tx{:tx-id 1, :tx-time #inst "2020-06-18T15:59:38.323-00:00"</code></pre></div></div></div></section><section id="_delete_3"><h2>Delete</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Using the same method as before you show Kaarlang the effect of this operation.</p></div>
<div class="paragraph"><p>Kaarlang is impressed it is that easy.
You point out that there are no longer any documents attached to the transactions.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/entity-history
(crux/db node #inst "2116-01-01T09")
:kaarlang/clients
:desc
{:with-docs? true})
#_#_
=> [{:crux.tx/tx-time #inst "2020-06-18T15:59:38.323-00:00",
:crux.tx/tx-id 2,
:crux.db/valid-time #inst "2115-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "0000000000000000000000000000000000000000",
:crux.db/doc nil}
{:crux.tx/tx-time #inst "2020-06-18T15:59:38.323-00:00",
:crux.tx/tx-id 2,
:crux.db/valid-time #inst "2114-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "0000000000000000000000000000000000000000",
:crux.db/doc nil}
{:crux.tx/tx-time #inst "2020-06-18T15:59:38.323-00:00",
:crux.tx/tx-id 2,
:crux.db/valid-time #inst "2113-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "0000000000000000000000000000000000000000",
:crux.db/doc nil}
{:crux.tx/tx-time #inst "2020-06-18T15:59:38.323-00:00",
:crux.tx/tx-id 2,
:crux.db/valid-time #inst "2111-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "0000000000000000000000000000000000000000",
:crux.db/doc nil}
{:crux.tx/tx-time #inst "2020-06-18T15:59:38.323-00:00",
:crux.tx/tx-id 2,
:crux.db/valid-time #inst "2110-01-01T09:00:00.000-00:00",
:crux.db/content-hash #crux/id "0000000000000000000000000000000000000000",
:crux.db/doc nil}
{:crux.tx/tx-time #inst "2020-06-18T15:59:38.323-00:00",
:crux.tx/tx-id 2,
:crux.db/valid-time #inst "2110-01-01T00:00:00.000-00:00",
:crux.db/content-hash #crux/id "0000000000000000000000000000000000000000",
:crux.db/doc nil}]</code></pre></div></div></div></section><section id="_kaarlang_2"><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You remember the secret note in your pocket and pass it to Kaarlang.</p></div></aside>
<div class="quoteblock speech"><blockquote><div class="paragraph"><p>I am grateful that you took the time to show me this.</p></div>
<div class="paragraph"><p>Today is a sad day for me as I have very much enjoyed my time here.</p></div>
<div class="paragraph"><p>Although, I was expecting to hear from a friend before I left.
There is a very important message that I am waiting for.</p></div></blockquote></div></div></section><section id="_the_secret_note"><h2>The Secret Note</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Kaarlang reads the note.</p></div>
<div class="paragraph"><p>He looks at you with the a peculiar facial expression.</p></div></aside>
<div class="quoteblock speech"><blockquote><div class="paragraph"><p>This is the note I was waiting for.</p></div>
<div class="paragraph"><p>It has information about the a top secret stellar transport shuttle.</p></div>
<div class="paragraph"><p>If you are interested in a great adventure, the shuttle comes once every hundred years or so to take a select few to a nearby star system.
The system is home to a mysterious hyper-intelligent form of life.</p></div>
<div class="paragraph"><p>I’m sure there would be a place for you if you were willing to help out.
The passengers on the shuttle have the right to be forgotten.
We need someone that can remove the passengers data from the solar system.</p></div>
<div class="paragraph"><p>What do you think?</p></div></blockquote></div></div></section></section>
<section><section id="_secret_location"><h2>Secret location</h2><div class="slide-content"><div class="imageblock" style=""><img src="oumuaua.jpg" alt="oumuaua"></div><aside class="notes"><div class="paragraph"><p>You arrive at the comet 'Oumuamua and pull along side, asking for permission to land.
A voice comes over the communications system</p></div></aside></div></section><section id="_arrival"><h2>Arrival</h2><div class="slide-content"><div class="quoteblock speech"><blockquote><div class="paragraph"><p>How did you find us? Who sent you??
— Mysterious person</p></div></blockquote></div>
<aside class="notes"><div class="paragraph"><p>"Kaarlang sent me"
You have permission to land</p></div></aside></div></section><section id="_space_port_10"><h2>Space Port</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You land on the space port and are ushered inside. The ships captain, Ilex, greets you.</p></div>
<div class="paragraph"><p>You are excited by the prospect and agree to help. First you read the manual entry for evict as this will be the perfect tool.</p></div></aside>
<div class="quoteblock speech"><blockquote><div class="paragraph"><p>Hello, it’s good to have you with us.</p></div>
<div class="paragraph"><p>We are set to leave the solar system right away and as part of our service we offer people the right to be forgotten. Some are not worried that their information is kept here, however others want there to be no personal data left behind.</p></div>
<div class="paragraph"><p>You may not have been told this yet, but this comet is actually a transportation vessel. It will take us to the star system Gilese 667C which is home to intelligent life far superior to our own. We all are hoping to find opportunities beyond our wildest dreams. All records of this transportation vessel and any life outside of the solar system are heavily monitored and wiped in the interest of preserving the normal technological advancement of the Human race. This means we know little of the beings we are going to meet.</p></div>
<div class="paragraph"><p>Our task for you is to remove the records of the people who have chosen to be forgotten here.</p></div></blockquote></div>
<div class="paragraph"><p>— Ilex, Captain</p></div></div></section><section id="_crux_manual_8" class="manual"><h2>Crux Manual</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You are given the data for the people on the ship and sync up your Crux node. You decide that you are going to embark on this adventure along with them so you add your name to the list.</p></div></aside>
<table class="tableblock frame-all grid-all" style="width:100%"><colgroup><col style="width:33.3333%"><col style="width:66.6667%"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Operation</th><th class="tableblock halign-left valign-top">Description</th></tr><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>put</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Writes a version of a document</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>delete</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Deletes a version of a document</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>match</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Stops a transaction if the precondition is not met.</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><code>evict</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Removes a document entirely</p></td></tr></table>
<div class="paragraph"><p><strong>Evict:</strong></p></div>
<div class="paragraph"><p>Crux supports eviction of active and historical data to assist with technical compliance for information privacy regulations.</p></div>
<div class="paragraph"><p>The main transaction log contains only hashes and is immutable.
All document content is stored in a dedicated document log that can be evicted by compaction.</p></div>
<div class="dlist"><dl><dt class="hdlist1">A complete evict transaction has the form</dt><dd><p><code>[:crux.tx/evict eid]</code></p></dd></dl></div></div></section><section id="_ingest_3"><h2>Ingest</h2><div class="slide-content"><div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx node
[[:crux.tx/put
{:crux.db/id :person/kaarlang
:full-name "Kaarlang"
:origin-planet "Mars"
:identity-tag :KA01299242093
:DOB #inst "2040-11-23"}]
[:crux.tx/put
{:crux.db/id :person/ilex
:full-name "Ilex Jefferson"
:origin-planet "Venus"
:identity-tag :IJ01222212454
:DOB #inst "2061-02-17"}]
[:crux.tx/put
{:crux.db/id :person/thadd
:full-name "Thad Christover"
:origin-moon "Titan"
:identity-tag :IJ01222212454
:DOB #inst "2101-01-01"}]
[:crux.tx/put
{:crux.db/id :person/johanna
:full-name "Johanna"
:origin-planet "Earth"
:identity-tag :JA012992129120
:DOB #inst "2090-12-07"}]])
;;=> #:crux.tx{:tx-id 0, :tx-time #inst "2020-06-18T16:11:03.410-00:00"}</code></pre></div></div></div></section><section id="_ingest_4"><h2>Ingest</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>Before you start the eviction process you make a query function so you can see the full results of anything stored in Crux:</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(defn full-query
[node]
(crux/q
(crux/db node)
'{:find [id]
:where [[e :crux.db/id id]]
:full-results? true}))</code></pre></div></div></div></section><section id="_results"><h2>Results</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You show the others the result:</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(full-query node)
#_#_
=> #{[{:crux.db/id :person/ilex,
:full-name "Ilex Jefferson",
:origin-planet "Venus",
:identity-tag :IJ01222212454,
:DOB #inst "2061-02-17T00:00:00.000-00:00"}]
[{:crux.db/id :person/thadd,
:full-name "Thad Christover",
:origin-moon "Titan",
:identity-tag :IJ01222212454,
:DOB #inst "2101-01-01T00:00:00.000-00:00"}]
[{:crux.db/id :person/kaarlang,
:full-name "Kaarlang",
:origin-planet "Mars",
:identity-tag :KA01299242093,
:DOB #inst "2040-11-23T00:00:00.000-00:00"}]
[{:crux.db/id :person/johanna,
:full-name "Johanna",
:origin-planet "Earth",
:identity-tag :JA012992129120,
:DOB #inst "2090-12-07T00:00:00.000-00:00"}]}</code></pre></div></div></div></section><section id="_evict"><h2>Evict</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>The Crux manual said that the evict operation will remove a document entirely. Ilex tells you the only person who whishes to exercise their right to be forgotten is Kaarlang.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(crux/submit-tx node [[:crux.tx/evict :person/kaarlang]])
;;=> #:crux.tx{:tx-id 3, :tx-time #inst "2020-06-18T16:13:03.276-00:00"}</code></pre></div></div></div></section><section id="_result_3"><h2>Result</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>You use your function and see that the transaction was a success.</p></div>
<div class="paragraph"><p>All the data associated with the specified :crux.db/id has been removed from the Crux along with the eid itself.</p></div></aside>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="language-clj" data-lang="clj">(full-query node)
#_#_
=> #{[{:crux.db/id :person/ilex,
:full-name "Ilex Jefferson",
:origin-planet "Venus",
:identity-tag :IJ01222212454,
:DOB #inst "2061-02-17T00:00:00.000-00:00"}]
[{:crux.db/id :person/thadd,
:full-name "Thad Christover",
:origin-moon "Titan",
:identity-tag :IJ01222212454,
:DOB #inst "2101-01-01T00:00:00.000-00:00"}]
[{:crux.db/id :person/johanna,
:full-name "Johanna",
:origin-planet "Earth",
:identity-tag :JA012992129120,
:DOB #inst "2090-12-07T00:00:00.000-00:00"}]}</code></pre></div></div></div></section><section id="_transaction_history"><h2>Transaction History</h2><div class="slide-content"><aside class="notes"><div class="paragraph"><p>This means the transactions will never be removed. You assure Ilex that the documents are completely removed from Crux, you can show this by looking at the history.</p></div>