Skip to content

Commit

Permalink
feat: Added discovery of Python peer from executors dir
Browse files Browse the repository at this point in the history
  • Loading branch information
beneboy committed Oct 14, 2019
1 parent c91af78 commit 6e93ea4
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 51 deletions.
52 changes: 30 additions & 22 deletions src/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,38 @@ replaceHandlers(data =>
})
)

// Discover other executors registered on this machine
// In the future this may attempt to discover remote executors as well
const manifests = discoverStdio()
if (manifests.length === 0) {
log.warn(
'No peer executors discovered on this machine. Executor will have limited capabilities.'
)
}
async function main() {
// Discover other executors registered on this machine
// In the future this may attempt to discover remote executors as well
const manifests = await discoverStdio()
if (manifests.length === 0) {
log.warn(
'No peer executors discovered on this machine. Executor will have limited capabilities.'
)
}

// Create a list of client types that can be used by executor
const clientTypes: ClientType[] = [StdioClient as ClientType]
// Create a list of client types that can be used by executor
const clientTypes: ClientType[] = [StdioClient as ClientType]

// Create executor that will served by servers
const executor = new Executor(manifests, clientTypes)
// Create executor that will served by servers
const executor = new Executor(manifests, clientTypes)

// Add server classes based on supplied options
const servers: Server[] = []
if (options.tcp !== undefined) {
servers.push(new TcpServer(executor, options.tcp))
}
if (servers.length === 0) {
log.warn(
'No servers specified in options (e.g. --tcp --stdio). Executor will not be accessible.'
)
// Add server classes based on supplied options
const servers: Server[] = []
if (options.tcp !== undefined) {
servers.push(new TcpServer(executor, options.tcp))
}
if (servers.length === 0) {
log.warn(
'No servers specified in options (e.g. --tcp --stdio). Executor will not be accessible.'
)
}

executor.start(servers)
}

executor.start(servers)
main()
.then(() => {})
.catch(err => {
log.error(err)
})
101 changes: 72 additions & 29 deletions src/stdio/discover.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,89 @@
import { Manifest } from '../base/Executor'
import { Transport } from '../base/Transports'
import * as path from 'path'
import * as os from 'os'
import * as fs from 'fs'
import * as util from 'util'
import { getLogger } from '@stencila/logga'

export default function discover(): Manifest[] {
const glob = util.promisify(require('glob'))

const log = getLogger('executa:serve')

const EXECUTORS_DIR_NAME = 'executors'

export default async function discover(): Promise<Manifest[]> {
// TODO: implement discovery of manifest files from ~/.stencila/executors/ (or similar)
// Should be able to mostly copy and paste from
// https://github.com/stencila/node/blob/24c30d1c89b5f6b6719a0beeda7a55d19401c294/lib/host/Host.js#L654-L666
// See https://github.com/stencila/executa/issues/2
return [python, js]
}

// These are just stubs to be replaced by JSON read in from manifest.json files...
let stencilaHome: string

const python: Manifest = {
capabilities: {
execute: {
type: 'object',
required: ['node'],
properties: {
node: {
type: 'object',
required: ['type', 'programmingLanguage'],
properties: {
type: {
enum: ['CodeChunk', 'CodeExpression']
},
programmingLanguage: {
enum: ['python']
}
}
}
}
switch (os.platform()) {
case 'darwin':
stencilaHome = path.join(
process.env.HOME !== undefined ? process.env.HOME : '',
'Library',
'Application Support',
'Stencila'
)
break
case 'linux':
stencilaHome = path.join(
process.env.HOME !== undefined ? process.env.HOME : '',
'.stencila'
)
break
case 'win32': // is 'win32' even on 64 bit windows systems
stencilaHome = path.join(
process.env.APPDATA !== undefined ? process.env.APPDATA : '',
'Stencila'
)
break
default:
stencilaHome = path.join(
process.env.HOME !== undefined ? process.env.HOME : '',
'stencila'
)
}
const executorsDir = path.join(stencilaHome, EXECUTORS_DIR_NAME)

const manifests: Manifest[] = []

const discoverDir = async (dir: string): Promise<Manifest | undefined> => {
// Check the folder exists (they may not e.g. if no packages have been registered)
try {
fs.accessSync(dir, fs.constants.R_OK)
} catch (error) {
return
}
},
addresses: {
stdio: {
type: Transport.stdio,
command: 'python3',
args: ['-m', 'stencila.schema', 'listen']
// For each host in the directory
for (const file of await glob(path.join(dir, '*.json'))) {
let json
try {
json = fs.readFileSync(file, { encoding: 'utf8' })
} catch (error) {
log.warn(`Warning: error reading file "${file}": ${error.message}`)
continue
}

try {
manifests.push(JSON.parse(json) as Manifest)
} catch (error) {
log.warn(`Warning: error parsing file "${file}": ${error.message}`)
}
}
}

await discoverDir(executorsDir)

manifests.push(js)
return manifests
}

// These are just stubs to be replaced by JSON read in from manifest.json files...

const js: Manifest = {
capabilities: {
execute: {
Expand Down

0 comments on commit 6e93ea4

Please sign in to comment.