Page MenuHomePhabricator

Consider an "API Utilities" application
Open, WishlistPublic

Description

Currently, we have several "support" applications (like Tokens, Subscribers, Flags, and Projects) that provide features to other applications.

Another possible support application is some kind of "API Utilities", either as part of Conduit or as a separate application.

Use cases are light on this, but I think it generally has fairly good properties conceptually if we can find enough things to motivate it. The primary use case today is something like this:

  • I want to create a task for each <external object> in <some bug tracker, repository, etc>.

There's no convenient way to:

  • Guarantee each external object gets exactly one internal object.
  • Look up the internal object.
  • Prevent users from messing up the relationship.
  • Do all of this in a light, ad-hoc way without custom code (no Doorkeeper, etc).

If we had some utilities for doing general locking/leasing/labeling, this might look like:

  • util.search for the object with label "X".
  • If it exists, great. Update it or whatever.
  • If it doesn't exist, create it, then util.label it (or util.atomic-label-and-publish it or whatever).

You can do this to some degree with custom fields or task titles, but they don't enforce uniqueness and users can edit them. You can disable that with editengine, but then you're configuring a bunch of stuff in weird different ways. It's also nice to be able to build this kind of synchronization logic purely into an external script without needing to rely on a particular custom field or editengine configuration. And this won't work for every application since not everything has full CustomField/EditEngine support.

In particular, useful primitives might include:

  • The ability to label an object with a unique label so that you can build an ad-hoc relationship between "external object X" and some Phabricator object.
  • The ability to lock or lease a label (or atomically publish an object) so if two copies of your script run at the same time they don't collide mid-flight.

A generic "Publish" capability for objects would grow out of T10215. See also T11440 for the manual version of this.

Event Timeline

This sounds REALLY useful. Relatedly, it would be useful if I could auto-generate a task for each recurrence of an event.

Or if I could relate other objects to events the way I can create relationships between tasks.

We actually do this ourselves in the "Locations" technical interview scenario: the script tries to create a set of tasks, or update them if they already exist. It currently uses title-based search to accomplish this, but could more reliably use "utility labels" if they existed.

https://secure.phabricator.com/source/locations/browse/publish/scripts/publish.php

I have spent a little time poking at code, trying to figure out how to build a simple template engine into the description field, so that you can reference hidden custom fields by {field-identifier} or similar from within the remarkup. I resigned myself to building something just like publish.php, where the descriptions are maintained via conduit, however, I still long for it to be built in.

Maybe another capability here is just letting callers put a random bag of properties on any object. I don't reaaaaally have use cases for that but it "seems powerful" if we're building all of this already at some point.

That does sound powerful. +1

After going quite a way down the rabbit hole of implementing something like this using a couple of custom fields + edit engine, I must say, what you've proposed here sounds a whole lot cleaner.

Essentially it'd be like an externally-usable custom edge type? Too bad this is a theoretical future thing, I'd love to be using it today.

We also technically do something like this in the production cluster today with bin/services sync, which (among other things) synchronizes Almanac services from the admin tier. The script currently just cheats and forces them to allocate with the same PHIDs, so we know local service X is the same as remote service X because they have the same PHID. I'm not sure we'd necessarily change this if we had a real "utilities" API but it's definitely a bit hacky as written today.