git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: f35512b739d69d270c0bdf1eb27644825a401674

Files: f35512b739d69d270c0bdf1eb27644825a401674 / actor.js

3207 bytesRaw
1const errors = require('./errors.json')
2const nope = () => {}
3
4module.exports = class Actor {
5 /**
6 * the Actor manages the various message passing functions and provides
7 * an interface for the containers to use
8 * @param {Object} opts
9 * @param {ID} opts.id - the UUID of the Actor
10 * @param {Object} opts.module - the module this actor was created from
11 * @param {Object} opts.state - the state of the module
12 * @param {Object} opts.storage - the actor's persistent storage
13 * @param {Object} opts.hypervisor - the instance of the hypervisor
14 * @param {Number} opts.nonce
15 * @param {Function} opts.Container - the module constructor and arguments
16 */
17 constructor (opts) {
18 Object.assign(this, opts)
19
20 this.ticks = 0
21 this.running = false
22 this.container = new this.Container(this)
23 if (!this.hypervisor.meter) {
24 this.incrementTicks = nope
25 }
26 }
27
28 /**
29 * Runs the shutdown routine for the actor
30 */
31 shutdown () {
32 // saves the nonce and storage to the state
33 this.state.value[1] = this.nonce
34 this.state.node[2] = {'/': this.storage}
35 }
36
37 /**
38 * Runs the startup routine for the actor
39 */
40 startup () {
41 return this.container.onStartup()
42 }
43
44 /**
45 * run the Actor with a given message
46 * @param {object} message - the message to run
47 * @param {String} method - which method to run
48 * @returns {Promise}
49 */
50 async runMessage (message) {
51 if (message._fromTicks > this.ticks) {
52 this.ticks = message._fromTicks
53 }
54 try {
55 this.currentMessage = message
56 await this.container.onMessage(message)
57 } catch (e) {
58 message.emit('execution:error', e)
59 }
60 message.emit('done', this)
61 }
62
63 /**
64 * updates the number of ticks that the actor has run
65 * @param {Number} count - the number of ticks to add
66 */
67 incrementTicks (count) {
68 this.currentMessage.funcRef.gas -= count
69 if (this.currentMessage.funcRef.gas < 0) {
70 throw new Error(errors.OUT_OF_GAS)
71 }
72 this.ticks += count
73 }
74
75 /**
76 * creates an actor from a module and code
77 * @param {Module} mod - the module
78 * @param {Buffer} code - the code
79 * @return {ActorRef}
80 */
81 newActor (mod, code) {
82 const modRef = this.createModule(mod, code)
83 return this.createActor(modRef)
84 }
85
86 /**
87 * creates a modref from a module and code
88 * @param {Module} mod - the module
89 * @param {Buffer} code - the code
90 * @return {ModuleRef}
91 */
92 createModule (mod, code) {
93 const id = this._generateNextId()
94 return this.hypervisor.createModule(mod, code, id)
95 }
96
97 /**
98 * creates an actor from a modref
99 * @param {ModuleRef} modRef - the modref
100 * @return {ActorRef}
101 */
102 createActor (modRef) {
103 const id = this._generateNextId()
104 return this.hypervisor.createActor(modRef, id)
105 }
106
107 _generateNextId () {
108 const id = {
109 nonce: this.nonce,
110 parent: this.id
111 }
112
113 this.nonce++
114 return id
115 }
116
117 /**
118 * sends a message
119 * @param {Message} message - the message
120 */
121 send (message) {
122 message._fromTicks = this.ticks
123 message._fromId = this.id
124
125 this.incrementTicks(message.funcRef.gas)
126 this.hypervisor.scheduler.queue([message])
127 }
128}
129

Built with git-ssb-web