Newer Questions (Alpha Release)
What is the relationship between REBOL/Services, Rugby, Beer, and Uniserve?
There is no strict relationship defined. REBOL/Services is intended to be transport protocol independent. In other words, you can use HTTP, CGI, direct TCP, Beer, or other methods. We don't want to re-invent those layers. We think they are masterful implementations. But, our main goal was to provide a standard request-response service model that takes advantage of the dialecting (domain-specific sublanguaging) strength of REBOL.
REBOL/Services defines a standard request-response service mechanism includes weak and strong encryption, public/private keys and certificates, service command discovery methods, defined standard default services, service contexts, and more. A primary goal was to make all that possible without exposing the inherent complexity of such features.
Who do I contact about changes, bugs, or suggestions?
Please contact Gabriele Santilli. He is the official RT representative for REBOL/Services. You can contact him on any of the AltME worlds, or by sending email to gabriele at REBOL dot com.
Is there an easy way to understand the essence of REBOL/Services?
Yes, it's like a human question and answer conversation. You make a request, you get a response. It's that simple.
The difference between this and other approaches is that the language of both the question and answer is REBOL itself. You can send the request:
sell 200 shares of "Microsoft" at US$20.01
and the service responds:
sold 200 shares of "Microsoft" at US$19.95
Also, such services are not restricted to just network usage, the are also handy between different processes on the same machine. If you are familiar with AREXX on the Amiga, than you know the power of that approach. Someday you will send your REBOL-based media player (a process running on the same machine):
play movie "Back to the Future" from 10:35:27 for 0:08
So, you get the idea.
How open is the design right now?
This is alpha 1. So, many parts of the design are open. If you have requirements, and want to contribute solutions, please do so now. It will be much more difficult to do so when it becomes beta.
Why does the Alpha 1 not use the built-in HTTP client handler?
It has to do with the history of development. REBOL/Services was targeted for the asynchronous kernel version of REBOL (which was experimental). That version did not yet implement async HTTP, so could not be used.
We plan to find a solution to this in Alpha 2 by either using the HTTP handler, or improving it as necessary to make that happen.
Will proxy connections be supported.
Yes. For HTTP, this is due to not using the HTTP handler above. We think it is very important to support proxies, and it will be done soon.
Will REBOL/Services provide a standard HTTP server for transport?
It was not our intention to write all the transport handlers. Normally, if you want to setup a non-standard service, you might as well use TCP directly. However, that certainly can be a problem in many environments that restrict direct TCP connections through firewalls, routers, etc.
So, it is our intention to include a minimal HTTP server within future versions. And, if we can find an existing server that meets our requirements, we'll be happy to add it!
Again, why not just use RPC?
RPC is inherently less flexible than dialecting. See the earlier FAQ below. Note it is possible to put one method on top of the other.
An additional note: The designer of REBOL/Services, Carl Sassenrath, is a pioneer and one of the first implementers of RPC based on a relationship with MIT back in the early 1980's. The restrictions of the RPC model coupled with the power of domain specific dialecting greatly influenced the primary design objectives of /Services.
What about the speed of REBOL/Services?
The speed of /Services is primarily dependent on the transport methods you are using. For example, if you are running via CGI, and the service must startup a script each time, that must be factored into the speed. If you are using direct TCP, with a service that is a permanent process, it will be quite fast. There are a lot in between.
However, also note that REBOL/Services encrypts every request and every response. It has no unencrypted mode. Therefore, due to the encryption and decryption overhead, it will always be slightly slower than other methods. However, we think the benefits are worth it.
Will timers be supported?
It is possible to add them to future alpha releases. Doing so will require clear definition of their usage and benefits.
Older Questions (Prior to Release)
What layer protocol is REBOL/Services?
This is an answer to questions like "how do you do a 100 MB file upload" or "how do I use it to sync files?"
REBOL/Services is a session layer protocol, not an application layer protocol (like the IOS app layer) or a transport layer protocol. At the session layer REBOL/Services manages the higher level connection, session variables and limits, authentication, encryption, request structure and interpretation, reply structure, error responses, and a few other things.
For pragmatic reasons, actions like large file transfers must be part of the application layer, not session layer. For example, a user typically needs to know that a large file transfer is underway so they understand why their connection is so busy (think about apps like file sharing tools that list in-progress transfers). In addition, large file transfers usually imply spooling and recovery actions on both sides of the connection, both of which are application-level features.
Would it be easier if services used the REBOL function argument dialect (RPC)?
One of the essential differences between REBOL/Services and RPC (remote procedure calls) is that communication interfaces are allowed to be full-fledged grammars (dialects). Another way to say this is that function argument specifications allow only a minor subset of the grammars possible as a dialect. This difference is important, because it allows service language domains to be tuned specifically to their usage (imagine a service interface that for efficiency reasons had rules like VID), rather than forcing them into a function domain. Also, if it was restricted to a function interface, we might as well implement RPC.
Another important point is that you can layer the service interface if you want. For instance, we could add a function-arg method of service interface definition that then builds the underlying parse rules. Or, you could even go so far to layer an entire RPC system on top of REBOL/Services, and I expect that will be done by someone rather soon.
Would it be useful to have access from other languages (Java, etc.)?
This is a good question that, unfortunately, does not have a simple answer. Indeed it may be useful to have access from other languages, but it would be difficult to provide "direct access" due to the nature and methods of REBOL. In other words, REBOL/Services are tuned to what REBOL does very well... and what most other languages do not do well at all. The best solution would be to provide an interface library to those other languages that performs the services on their behalf. That library would in fact be REBOL, but we can just call it the "service interface library" to keep from freaking them out.
Can a service access the result port (e.g. send-service itself)?
Yes, I've made sure that the result port is accessible in both the client and server APIs. This is an important design feature of REBOL/Services: the connection port is the primary access object (this also helps explain "why function" not "object" interface, more on that below). Ports can always be reached from session objects (and sessions can be reached from ports, as well as via a session management list).
With regard to load-balancing (the main reason the question was asked), I think that would be better if it were transparent to the REBOL/Services interface. To do so requires a proxy at the transport layer, not the session layer (correct me if you think I am wrong here). This is similar to how IOS implements its proxy on port 80.
Can Service Contexts be nested?
We need more discussion on this to decide if we really want to allow that. I implemented it, but then commented the code out. My big concern was the overloading (overlaying) of command sets, and possible serious usage errors that may occur when a user makes an invalid request in one context that is valid in a lower context. This can be "one of those great features" but also "one of those horrible bugs". I can say more about it if you like...
Why aren't errors mentioned in the nutshell doc?
This is too deep a subject for a nutshell doc. There are many kinds of errors that can occur. I briefly mentioned command errors in the doc - those are the most important ones for beginners, but there will need to be a lot more info on errors in other tech docs.
Can a REBOL Service call another REBOL Service?
Yes, it was designed to allow this. It should work fine in direct TCP; however, in some transport mechanisms (such as CGI), it can be problematic if there are any major delays in the secondary service (because the HTTP server could timeout and terminate the CGI session).
Why does it use a function interface?
I wanted to use a PORT as the primary service object (taking advantage of all those built-in features) and not add an additional datatype to REBOL. Some of you will also notice that the functions somewhat mirror those of my Amiga OS message port design. That is intentional.
I also thought about the pragmatic usage side. Verb-noun is standard in REBOL, and using -service makes the interface easier for help search, as some of you noticed. Although, you also noted that the primary object of the functions can be different (spec, port, request), I think that is ok. I see no benefit in an object/function interface here, and in fact I would go further to say that this is exactly one of those cases where such a model would fall apart... because the consistency of the interface is abstract, not concrete. In such cases, ordinary functions are closer to what our human-language-oriented brains like to deal with.
What about a higher-level port scheme? That may be possible once we provide a name-to-service directory (which is planned, but not yet implemented). In that case we could use a scheme such as REBOL (or our TLA name) to indicate the REBOL/Service namespace mapping to actual service location and protocol. That would be handy. For example:
do-service rebol://global-time-service [time]
This actually takes us close to our original RNA (REBOL Network Architecture) discussed a bit in earlier days.
SEND-SERVICE vs SEND
In the original design of REBOL, I really wanted SEND to be useful for more than just email. I still do. The abstraction of the SEND function is:
send target message
For email, the target is an email address. However, it could just as well be a server (service). I especially wanted the form:
send rebol:local/task message
However, a problem occurs when you consider the rest of the interface. WAIT and WAIT-SERVICE, although strongly related, are not the same function. There are similar issues with OPEN, CLOSE, DO, and QUERY, which would not work unless we used a scheme for REBOL/Services (see above). That may eventually be possible as a future goal.
Simplified results for DO-SERVICE
It looks like we might all agree that we should not simplify the DO-SERVICE return value. That means that it would not work like the LOAD function:
count: load %counter.r count: do-service tcp://service.example.com [count]
where count is an integer number.
Instead, the user would write:
result: do-service tcp://service.example.com [count] count: result/2/1
Of course, this assumes that the request did not have an error, and this is also different than the simplified case. The reason is that in the simplified case a command error would cause a local error throw. That no longer happens in the simplified case. An explicit check is now required. To check for failure, the above code would need to become:
result: do-service tcp://service.example.com [count] either result/1 = 'ok [ count: result/2/1 ][ print "error!" ]
So consistency with the "long-form" of results will cost us that too.
So... perhaps we are not done discussing this yet? Why? Because the main purpose of DO-SERVICE is that of simplification!
PUT and GET
The file service shows examples that use PUT and GET commands to mimic the FTP and HTTP commands. I considered using READ and WRITE (because those are REBOL's words), but I felt those were really not the same thing. This was almost one of those toss-of-the-coin type of things, and I am open to more discussion on those command names.
REBOL/Services Vocabulary: Commands VS Functions
I've decided that the proper name of the verb actions within dialects is command. They are not functions in the REBOL sense.
This is a fine point, but one that I stress because I want to avoid the situation we've had before where some people would call functions "commands" - like those used in BASIC or a command shell.
The commands of a REBOL/Services dialect should be thought of much more like those of a command shell. So, here the name is appropriate.
Use of Command Paths
Remember that the abstraction of REBOL paths is that of refinement of specification. So it seemed very natural to me to allow the form:
To refer to a command within a specific service.
Note, however, that I'm not so sure I would take that any further, but I suppose that is debatable.
In addition, because services use a dialect, not a function, it is pretty easy to write commands that allow optional word specifications without the need for inserting them into the command:
file/get checksum %file newer-than 20-Mar-2005
There is a lot of power in this kind of interface.
The SERVICE Command
The SERVICE command is a default command that lets you "focus" a command set on a specific service context. (In AREXX I think it was the word "command".)
I like the word SERVICE for this command because it is fairly clear as a single command what it does (selects the SERVICE context by name).
More Comments on the Service Command Dialect
For a nutshell doc, I did not want to get into the details very much. But, as you can tell from my above comments, there is more to it. It is essentially a PARSE rule block. The main difference is that I needed a way to embed documentation within it. I thought about that for a while, and I really decided that I did not want the docs to be external to the commands. We programmers are lazy about docs, and if we don't type them in during our coding stages, they may never get written.
So, the command dialect gets parsed and the strings get extracted into a separate block that is used for making "discovery" queries on the service. That is further expanded by the fact that we need to support multiple languages within the text of those docs. That meant that I could no longer simply use the string datatype as the meta escape, I needed to provide another escape, and I picked a specific ISSUE! datatype to do that. These kinds of things just come down to a compromise on what is the easiest to use and remember. I will be saying more about this in later docs.
Can Services be Hot-Swapped?
That is a goal, but it's not yet tested. Each service is defined by an object within a lookup directory, so the object can be replaced. There might be some issues that could pop up... because servers are allowed to process multiple simultaneous service requests. But then, that fact can open a tarpit of other issues... most of which are never really a problem, as we learned in IOS.
Do multiple-command requests need to finish before the return?
Yes. Requests are "atomic". When multiple commands are sent in the same request, you get all the command results at the same time. However, if you want requests to be sent back as they are completed, just send them as separate requests. You do not need to wait for a result before sending the next request.