-
Notifications
You must be signed in to change notification settings - Fork 4
Plugin requirements
- A POST request containing, in the request header, a JSON-encoded set of artifact IDs along with synonyms, like this:
{
<id>: { // the id the user entered for this artifact
"doi": <doi>, // set to bool FALSE if unavailable, as are all below
"url":<url>,
"pmid":<pubmed id>
},
<id>: {
"doi": <doi>,
"url":<url>,
"pmid":<pubmed id>
},
...
}
For external plugins (running on other people's servers), the mechanics of this are not our concern. For local plugins, though, we need to handle the REST interface. To do this, Jason is replacing the old system with this one: each plugin is an appropriately-named directory. Each directory contains index.php, which for Python plugins will contain this:
<?php
$pluginName = "plugin.py";
$input = escapeshellarg(file_get_contents("php://input"));
echo exec("python $pluginName $input");
?>
This is nothing more than a wrapper that calls the Python code and prints the output. The advantage to this is that plugin writers fluent in Python can control the entire behaviour of their plugins, and there is clear division of responsibility. The plugin directory is entirely self-contained and calls no other code.
- filter those IDs so that only relevant ones are sent to Source API
- for each relevant ID, note what type of artifact it is (article, slideshow, etc)
- chunk them together if their Source API gets down like that
- make as many calls as needed to their Source API to get data on everything.
- pause before each call, if needed to handle rate limiting (eg, for Delicious)
- do error checking on what they get back from the Source and handle things appropriately
- Plugins should use exponential backoff to handle bad responses from Source APIs. For now, the maximum wait interval should be 30 seconds or so, then an error should be thrown.
- Errors are reported in the appropriate field in the response object
- In the future, plugins may want to cache responses
- Plugins may want to log reponses
{
"source_name": "Mendeley",
"last_update": "1306599479", // unix timestamp as string
"has_error": FALSE, // (bool, not str) or TRUE if there is a valid error_msg
"error_msg": "NA" // message string if has_error=="TRUE", like "API limit reached"
"about": {
"descr": "A research management tool for desktop and web.",
"url": "http://www.mendeley.com/",
"icon": "http://www.mendeley.com/favicon.ico",
"metrics": {
"readers": "the number of readers of the article",
"groups": "the number of groups the article is in"
}
},
"artifacts": { // only return artifacts the plugin can grok (eg, this plugin would discard URLs)
"10.1371/journal.pbio.0060048": {
"type": "article", // required for all plugins; all other attributes are plugin-specific, and match the list in about.metrics
"readers": 24, // can be number(±int, 0, float), string, or array of objects (tweets, for instance)
"groups": 3
},
"10.1371/journal.pone.00008109": {
"type": "article",
"readers": 0,
"groups": 0
}
}
}
There are three things that plugins can return:
- counts of things (eg, "10 readers")
- the things themselves (eg, an array of tweets, each with its own metadata)
- artifact metadata (eg, its title)
All of these can be accommodated within the present structure; each artifact gets a bunch of key:value pairs encoding one of these. This way the same plugin can return different return types.
Note that plugins no longer return "NA" for things; there's nothing we'd want to do with these, so we might as well just not return 'em; it simplifies things downstream.