kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/serving/api/api.go (about)

     1  /*
     2   * Copyright 2015 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  // Package api provides a union of the filetree, xrefs, and graph interfaces
    18  // and a command-line flag parser.
    19  package api // import "kythe.io/kythe/go/serving/api"
    20  
    21  import (
    22  	"context"
    23  	"flag"
    24  	"fmt"
    25  	"os"
    26  	"strings"
    27  
    28  	"kythe.io/kythe/go/services/filetree"
    29  	"kythe.io/kythe/go/services/graph"
    30  	"kythe.io/kythe/go/services/xrefs"
    31  	ftsrv "kythe.io/kythe/go/serving/filetree"
    32  	gsrv "kythe.io/kythe/go/serving/graph"
    33  	"kythe.io/kythe/go/serving/identifiers"
    34  	xsrv "kythe.io/kythe/go/serving/xrefs"
    35  	"kythe.io/kythe/go/storage/leveldb"
    36  	"kythe.io/kythe/go/storage/table"
    37  
    38  	ftpb "kythe.io/kythe/proto/filetree_go_proto"
    39  	gpb "kythe.io/kythe/proto/graph_go_proto"
    40  	ipb "kythe.io/kythe/proto/identifier_go_proto"
    41  	xpb "kythe.io/kythe/proto/xref_go_proto"
    42  )
    43  
    44  // Interface is a union of the xrefs and filetree interfaces.
    45  type Interface interface {
    46  	xrefs.Service
    47  	graph.Service
    48  	filetree.Service
    49  	identifiers.Service
    50  
    51  	// Close releases the underlying resources for the API.
    52  	Close(context.Context) error
    53  }
    54  
    55  const (
    56  	// CommonDefault is the common Kythe default API specification for Flag
    57  	CommonDefault = "https://xrefs-dot-kythe-repo.appspot.com"
    58  
    59  	// CommonFlagUsage is the common Kythe usage description used for Flag
    60  	CommonFlagUsage = "Backing API specification (e.g. JSON HTTP server: https://xrefs-dot-kythe-repo.appspot.com or local serving table path: /var/kythe_serving)"
    61  )
    62  
    63  // Flag defines an api Interface flag with specified name, default value, and
    64  // usage description.  The return value is the address of an Interface variable
    65  // that stores the value of the flag.
    66  func Flag(name, value, usage string) *Interface {
    67  	val := &apiFlag{}
    68  	val.Set(value)
    69  	flag.Var(val, name, usage)
    70  	return &val.api
    71  }
    72  
    73  // ParseSpec parses the given specification and returns an opened handle to an
    74  // API Interface.  The following formats are currently supported:
    75  //   - http:// URL pointed at a JSON web API
    76  //   - https:// URL pointed at a JSON web API
    77  //   - local path to a LevelDB serving table
    78  func ParseSpec(apiSpec string) (Interface, error) {
    79  	api := &apiCloser{}
    80  	if strings.HasPrefix(apiSpec, "http://") || strings.HasPrefix(apiSpec, "https://") {
    81  		api.xs = xrefs.WebClient(apiSpec)
    82  		api.gs = graph.WebClient(apiSpec)
    83  		api.ft = filetree.WebClient(apiSpec)
    84  		api.id = identifiers.WebClient(apiSpec)
    85  	} else if _, err := os.Stat(apiSpec); err == nil {
    86  		db, err := leveldb.Open(apiSpec, nil)
    87  		if err != nil {
    88  			return nil, fmt.Errorf("error opening local DB at %q: %v", apiSpec, err)
    89  		}
    90  		api.closer = func(ctx context.Context) error { return db.Close(ctx) }
    91  
    92  		ctx := context.Background()
    93  		api.xs = xsrv.NewService(ctx, db)
    94  		api.gs = gsrv.NewService(ctx, db)
    95  		tbl := &table.KVProto{db}
    96  		api.ft = &ftsrv.Table{tbl, true}
    97  		api.id = &identifiers.Table{tbl}
    98  	} else {
    99  		return nil, fmt.Errorf("unknown API spec format: %q", apiSpec)
   100  	}
   101  	return api, nil
   102  }
   103  
   104  type apiFlag struct {
   105  	spec string
   106  	api  Interface
   107  }
   108  
   109  // Set implements part of the flag.Value interface.
   110  func (f *apiFlag) Set(spec string) error {
   111  	api, err := ParseSpec(spec)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	f.spec = spec
   116  	f.api = api
   117  	return nil
   118  }
   119  
   120  // String implements part of the flag.Value interface.
   121  func (f *apiFlag) String() string { return f.spec }
   122  
   123  // apiCloser implements Interface
   124  type apiCloser struct {
   125  	xs xrefs.Service
   126  	gs graph.Service
   127  	ft filetree.Service
   128  	id identifiers.Service
   129  
   130  	closer func(context.Context) error
   131  }
   132  
   133  // Close implements part of Interface.
   134  func (api apiCloser) Close(ctx context.Context) error {
   135  	if api.closer != nil {
   136  		return api.closer(ctx)
   137  	}
   138  	return nil
   139  }
   140  
   141  // Nodes implements part of the graph Service interface.
   142  func (api apiCloser) Nodes(ctx context.Context, req *gpb.NodesRequest) (*gpb.NodesReply, error) {
   143  	return api.gs.Nodes(ctx, req)
   144  }
   145  
   146  // Edges implements part of the graph Service interface.
   147  func (api apiCloser) Edges(ctx context.Context, req *gpb.EdgesRequest) (*gpb.EdgesReply, error) {
   148  	return api.gs.Edges(ctx, req)
   149  }
   150  
   151  // Decorations implements part of the xrefs Service interface.
   152  func (api apiCloser) Decorations(ctx context.Context, req *xpb.DecorationsRequest) (*xpb.DecorationsReply, error) {
   153  	return api.xs.Decorations(ctx, req)
   154  }
   155  
   156  // CrossReferences implements part of the xrefs Service interface.
   157  func (api apiCloser) CrossReferences(ctx context.Context, req *xpb.CrossReferencesRequest) (*xpb.CrossReferencesReply, error) {
   158  	return api.xs.CrossReferences(ctx, req)
   159  }
   160  
   161  // Documentation implements part of the xrefs Service interface.
   162  func (api apiCloser) Documentation(ctx context.Context, req *xpb.DocumentationRequest) (*xpb.DocumentationReply, error) {
   163  	return api.xs.Documentation(ctx, req)
   164  }
   165  
   166  // Directory implements part of the filetree Service interface.
   167  func (api apiCloser) Directory(ctx context.Context, req *ftpb.DirectoryRequest) (*ftpb.DirectoryReply, error) {
   168  	return api.ft.Directory(ctx, req)
   169  }
   170  
   171  // CorpusRoots implements part of the filetree Service interface.
   172  func (api apiCloser) CorpusRoots(ctx context.Context, req *ftpb.CorpusRootsRequest) (*ftpb.CorpusRootsReply, error) {
   173  	return api.ft.CorpusRoots(ctx, req)
   174  }
   175  
   176  // Find implements part of the identifiers Service interface.
   177  func (api apiCloser) Find(ctx context.Context, req *ipb.FindRequest) (*ipb.FindReply, error) {
   178  	return api.id.Find(ctx, req)
   179  }