You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+83-70Lines changed: 83 additions & 70 deletions
Original file line number
Diff line number
Diff line change
@@ -4,105 +4,118 @@
4
4
5
5
## Introduction
6
6
7
-
ServiceX DID finders take a dataset name and turn them into files to be transformed. They interact with ServiceX via the Rabbit MQ message broker. As such, the integration into ServiceX and the API must be the same for all DID finders. This library abstracts away some of that interaction so that the code that interacts with ServiceX can be separated from the code that translates a dataset identifier into a list of files.
7
+
ServiceX DID finders take a dataset name and turn them into files to be transformed. They are
8
+
implemented as a Celery application with a task called `do_lookup`. Developers of a specific
9
+
DID Finder implementation need to write a generator function which yields a dictionary for each
10
+
file in the dataset.
8
11
9
-
The DID Finder author need write only a line of initialization code and then a small routine that translates a DID into a list of files.
12
+
The Task interacts with ServiceX through the App's REST endpoint to add files to the dataset and
13
+
a separate REST endpoint to signal that the dataset is complete.
10
14
11
-
## Usage
15
+
The app caches DID lookups. The `dataset_id` is the primary key for the cache table.
12
16
13
-
A very simple [demo](https://github.com/ssl-hep/ServiceX_DID_Finder_Demo) has been created to show how to make a basic DID finder for ServiceX. You can use that as a starting point if authoring one.
17
+
Invocations of the `do_lookup` task accepts the following arguments:
18
+
*`did`: The dataset identifier to look up
19
+
*`dataset_id`: The ID of the dataset in the database
20
+
*`endpoint`: The ServiceX endpoint to send the results to
21
+
*`user_did_finder`: The user callback that is a generator function that yields file information dictionaries.
14
22
15
-
Create an async callback method that `yield`s file info dictionaries. For example:
23
+
## Creating a DID Finder
24
+
You start with a new Python project. You will need to add this library as a dependency to the project
25
+
by adding the following to your `pyproject.tom` file:
16
26
27
+
```
28
+
servicex-did-finder-lib = "^3.0"
29
+
```
30
+
31
+
Create a script that will run your DID. It needs to contain your generator function that adheres
*`did_name`: the name of the DID that you should look up. It has the schema stripped off (e.g. if the user sent ServiceX `rucio://dataset_name_in_rucio`, then `did_name` will be `dataset_name_in_rucio`)
31
-
*`info` contains a dict of various info about the request that asked for this DID.
43
+
*`info` contains a dict of various info about the database ID for this dataset.
44
+
*`did_finder_args` contains the arguments that were passed to the DID finder at startup. This is a way to pass command line arguments to your file finder
32
45
33
-
Yield the results as you find them - ServiceX will actually start processing the files before your DID lookup is finished if you do this. The fields you need to pass back to the library are as follows:
46
+
Yield the results as you find them. The fields you need to pass back to the library are as follows:
34
47
35
48
*`paths`: An ordered list of URIs that a transformer in ServiceX can access to get at the file. Often these are either `root://` or `http://` schema URI's. When accessing the file, URIs will be tried in ordered listed.
36
49
*`adler32`: A CRC number for the file. This CRC is calculated in a special way by rucio and is not used. Leave as 0 if you do not know it.
37
50
*`file_size`: Number of bytes of the file. Used to calculate statistics. Leave as zero if you do not know it (or it is expensive to look up).
38
51
*`file_events`: Number of events in the file. Used to calculate statistics. Leave as zero if you do not know it (or it is expensive to look up).
39
52
40
-
Once the callback is working privately, it is time to build a container. ServiceX will start the container and pass, one way or the other, a few arguments to it. Several arguments are required for the DID finder to work (like `rabbitUrl`). The library will automatically parse these during initialization.
41
-
42
-
To initialize the library and start listening for and processing messages from RabbitMQ, you must initialize the library. In all cases, the call to `start_did_finder` will not return.
43
-
44
-
If you do not have to process any command line arguments to configure the service, then the following is good enough:
53
+
Here's a simple example of a did handler generator:
raiseRuntimeError(f"No files found matching {did_name} for request "
66
+
f"{info['request-id']} - are you sure it is correct?")
67
+
68
+
for url in urls:
69
+
yield {
70
+
'paths': [url],
71
+
'adler32': 0, # No clue
72
+
'file_size': 0, # We could look up the size but that would be slow
73
+
'file_events': 0, # And this we do not know
74
+
}
48
75
```
49
76
50
-
The first argument is the name of the schema. The user will use `my_finder://dataset_name` to access this DID lookup (and `my_callback` is called with `dataset_name` as `did_name`). Please make sure everything is lower case: schema in URI's are not case sensitive.
77
+
There is a small amount of additional boilerplate code that is required to create a DID Finder. This
78
+
is the code that will create the Celery app and register your function as a task. Here is an
79
+
example (which assumes that `find_files` is your DID handler):
If you do need to configure your DID finder from command line arguments, then use the python `argparse` library, being sure to hook in the did finder library as follows (this code is used to start the rucio finder):
93
+
## Extra Command Line Arguments
94
+
Sometimes you need to pass additional information to your DID Finder from the command line. You do
95
+
this by creating your own `ArgParser` and then calling the `add_did_finder_cnd_arguments` method
96
+
which inserts the arguments that the library needs to pass to the finder. Here is an example:
1. The call to `add_did_finder_cnd_arguments` to setup the arguments required by the finder library.
102
-
2. Parsing of the arguments using the usual `parse_args` method
103
-
3. Passing the parsed arguments to `start_did_finder`.
116
+
These parsed args will be passed to your `find_files` function as a dictionary in
117
+
the `did_finder_args` parameter.
104
118
105
-
Another pattern in the above code that one might find useful - a thread-safe way of passing global arguments into the callback. Given Python's Global Interpreter Lock, this is probably not necessary.
106
119
107
120
### Proper Logging
108
121
@@ -124,7 +137,7 @@ In the end, all DID finders for ServiceX will run under Kubernetes. ServiceX com
124
137
}
125
138
```
126
139
127
-
The `start_did_finder` will configure the python root logger properly.
140
+
The `DIDFinderApp` will configure the python root logger properly.
0 commit comments