code: func (s *SchedulerServer) GetJobs(ctx context.Context, in *scheduler.JobsRequest) (*scheduler.JobsReply, error) {
  	if in.GetCursor() != "" {
  		// Paging in GetJobs isn't implemented until we have enough jobs to care.
  		// Until then, not empty cursor implies no more jobs to return.
  		return &scheduler.JobsReply{Jobs: []*scheduler.Job{}, NextCursor: ""}, nil
  	}
  	var ejobs []*engine.Job
  	var err error
  	if in.GetProject() == "" {
  		ejobs, err = s.Engine.GetVisibleJobs(ctx)
  	} else {
  		ejobs, err = s.Engine.GetVisibleProjectJobs(ctx, in.GetProject())
  	}
  	if err != nil {
  		return nil, status.Errorf(codes.Internal, "internal error: %s", err)
  	}
  
  	jobs := make([]*scheduler.Job, len(ejobs))
  	for i, ej := range ejobs {
  		traits, err := presentation.GetJobTraits(ctx, s.Catalog, ej)
  		if err != nil {
  			return nil, status.Errorf(codes.Internal, "failed to get traits: %s", err)
  		}
  		jobs[i] = &scheduler.Job{
  			JobRef: &scheduler.JobRef{
  				Project: ej.ProjectID,
  				Job:     ej.JobName(),
  			},
  			Schedule: ej.Schedule,
  			State: &scheduler.JobState{
  				UiStatus: string(presentation.GetPublicStateKind(ej, traits)),
  			},
  			Paused: ej.Paused,
  		}
  	}
  	return &scheduler.JobsReply{Jobs: jobs, NextCursor: ""}, nil
  }
docs: // GetJobs fetches all jobs satisfying JobsRequest and visibility ACLs.